Environment variables
Copy .env.example to .env (root) and apps/web/.env. Never commit .env.
| Variable | Required | Default | Description | ||||
|---|---|---|---|---|---|---|---|
DATABASE_URL | yes | – | PostgreSQL connection string (Prisma + pg-boss). Use ?schema=public. | ||||
SESSION_SECRET | yes | – | ≥32 random characters. Signs session cookies and authoring tokens, and encrypts per-project Anthropic keys. Rotating it invalidates all authoring tokens, and projects with their own Anthropic key must enter it again (Scout uses ANTHROPIC_API_KEY meanwhile, if set). | ||||
APP_URL | yes | http://localhost:3000 | Public dashboard origin. Used for CSRF origin checks, invite links and the authoring postMessage origin. | ||||
NEXT_PUBLIC_GUIDELY_API_URL | no | APP_URL | SDK API base URL as seen from customer browsers. Shown in install snippets; read at runtime, so it can be set on the container rather than at image build. | ||||
NEXT_PUBLIC_GUIDELY_CDN_URL | no | ${API_URL}/sdk/guidely.js | Where the script-tag build is served from. | ||||
REDIS_URL | no | – | Enables Redis-backed rate limiting and config cache. In-memory fallback when unset (fine for one replica). | ||||
EVENT_RETENTION_DAYS | no | 365 | Default retention for product events (projects can override in Privacy settings). | ||||
WORKER_ENABLED | no | true | Informational; run pnpm worker as a separate process. | ||||
LOG_LEVEL | no | info | debug \ | info \ | warn \ | error. Logs are JSON lines. | |
SEED_DEMO | no | true | Set false to skip the demo workspace in pnpm db:seed. | ||||
SENTRY_DSN | no | – | Hook point: captureException in src/server/logger.ts is where to plug an error tracker. | ||||
PRISMA_LOG | no | – | query to log SQL in development. | ||||
GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET | no | – | Enable Continue with GitHub. Create an OAuth App on GitHub with callback URL ${APP_URL}/api/v1/auth/github/callback. | ||||
GITHUB_ALLOWED_ORGS | no | – | Comma-separated GitHub organization logins. Each listed org gets a shared workspace (gh-<org>, first member Owner) the first time one of its members signs in, with the org as that workspace's auto-join rule. When set, GitHub users who match no workspace (membership, auto-join rule or invitation) are refused even with open signup. | ||||
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | no | – | Enable Continue with Google. Create an OAuth client (type Web application) in Google Cloud with redirect URI ${APP_URL}/api/v1/auth/google/callback. Which Google accounts get in is decided per workspace (Settings → Sign-in → Google Workspace domains, invitations). Empty or REPLACE_ME = off. | ||||
AUTH_PASSWORD_ENABLED | no | true | false disables email/username + password login everywhere (GitHub / Google only). Workspaces can also turn password sign-in off for themselves. | ||||
AUTH_SIGNUP_ENABLED | no | true | false closes self-service signup: new people then need an invitation, a login created by a workspace admin, or a matching workspace auto-join rule. Invited people can still create a password account. | ||||
PLATFORM_ADMIN_EMAILS | no | – | Comma-separated emails of platform admins, who can manage every workspace at /admin. Only honoured for verified emails (GitHub sign-in); grant others from the console or with pnpm --filter @guidelytech/web admin:grant <email>. | ||||
ANTHROPIC_API_KEY | no | – | Server-wide key that lets Scout answer messenger questions with AI and draft articles from uploaded files. Projects can set their own key in Scout settings, which takes precedence. With neither (or an empty/REPLACE_ME value) the messenger still works and every conversation goes to the team inbox. Requests go to the Anthropic API; see security. | ||||
SCOUT_MODEL | no | claude-opus-5 | Claude model Scout uses. | ||||
SCOUT_EFFORT | no | medium | low \ | medium \ | high \ | xhigh \ | max. Higher is more thorough and slower/costlier. |
SMTP_URL | no | – | SMTP connection URL for inbox notification emails, e.g. smtps://user:pass@smtp.example.com:465. When unset emails are logged instead. Locally: docker compose --profile mail up -d and smtp://localhost:51025 (Mailpit UI on :58025). | ||||
EMAIL_FROM | no | Guidely <no-reply@guidely.app> | From address for notification emails. | ||||
REPLAY_S3_BUCKET | for session replay | – | S3 bucket that stores session recordings. Without it session replay is unavailable (the SDK is told not to record). Locally guidely-replays on the SeaweedFS container from pnpm db:up. | ||||
REPLAY_S3_REGION | no | us-east-1 | Bucket region. | ||||
REPLAY_S3_ENDPOINT | no | – | Custom S3 endpoint for S3-compatible storage (http://localhost:59000 locally and in CI). Leave unset on AWS. | ||||
REPLAY_S3_FORCE_PATH_STYLE | no | false | true for path-style addressing (needed by SeaweedFS/MinIO). | ||||
REPLAY_S3_PREFIX | no | replays | Key prefix; objects are <prefix>/<projectId>/<recordingId>/<pageLoadId>/<seq>.json.gz. | ||||
MEDIA_PUBLIC_URL | no | – | Base URL of a cookieless CDN serving the bucket's media/ keys as paths (e.g. https://media.guidelytech.com; the infra stack sets it to its CloudFront distribution). New article uploads link there; unset, they link to the app's /api/v1/media/… route, which keeps serving older links either way. Use a host the dashboard's cookies are never sent to. | ||||
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY | no | – | S3 credentials via the standard AWS chain. Locally any value works against SeaweedFS; on AWS the ECS task role is used instead. | ||||
SKIP_MIGRATIONS | no | false | Container only: skip prisma migrate deploy at start. | ||||
DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD | no | – | Container only: composed into DATABASE_URL when it is not set (used by the AWS stack with Secrets Manager). |
Demo apps:
| Variable | App | Description |
|---|---|---|
NEXT_PUBLIC_GUIDELY_PROJECT_ID, NEXT_PUBLIC_GUIDELY_ENV, NEXT_PUBLIC_GUIDELY_API_URL | apps/demo-react | Public environment key, environment name, API URL. |
VITE_GUIDELY_PROJECT_ID, VITE_GUIDELY_ENV, VITE_GUIDELY_API_URL | apps/demo-svelte | Same for SvelteKit. |
Public keys are not secrets. A pk_… key only identifies an environment and unlocks its published configuration and event ingestion, further restricted by the environment's allowed origins. Dashboard credentials never reach the browser SDK.