Skip to content

Environment variables

Every environment variable a Monark deployment reads, grouped by the service that reads it. "Required" means the service refuses to start, or the named feature fails, without it.

<!-- source: services/api/src/lib/env.ts, services/api/.env.example, services/web/.env.example, render.yaml, packages/*/src -->

Quote any value that starts with #, such as a hex colour: BRANDING_PRIMARY="#2563EB". Node's --env-file parser and the Render dashboard read an unquoted # as the start of a comment, so the value becomes empty.

API service (services/api)

Set in services/api/.env locally and on the monark-api / monark-api-staging Render services. Variables marked "not in render.yaml" must be added by hand under the service's Environment.

Runtime and network

VariableRequiredDefaultWhat it does
NODE_ENVnodevelopmentdevelopment, test or production. Production tightens CORS to WEB_ORIGIN only. Render sets production.
PORTno4000Port the api listens on (bound to 0.0.0.0).
WEB_ORIGINyeshttp://localhost:3000,http://127.0.0.1:3000Comma-separated CORS and cookie allowlist: the web app's origin. In development, any private-network origin is also accepted.
APP_URLyeshttp://localhost:3000Web app origin used to build links in emails when no request host is available (crons, scripts).
LOG_LEVELnoinfoLog level for the structured logger.
SERVICE_NAMEnomonarkValue of the service field on every log line. Not in render.yaml.

Database and Supabase

VariableRequiredDefaultWhat it does
DATABASE_URLyesnonePostgres connection used at runtime. On Supabase, the transaction pooler URL (port 6543).
DIRECT_URLyesnoneDirect Postgres connection (port 5432), used by prisma migrate deploy.
SUPABASE_URLyesnoneSupabase project URL. The api exits at boot if it's missing.
SUPABASE_PUBLISHABLE_KEYyesnoneSupabase publishable (formerly anon) key; signup creates the auth user through it.
SUPABASE_SECRET_KEYyesnoneSupabase secret (formerly service_role) key for admin operations and file storage.

Secrets and keys

VariableRequiredDefaultWhat it does
TOTP_ENCRYPTION_KEYfor two-factornone32 bytes as 64 hex characters. Encrypts two-factor secrets at rest. Changing it invalidates every enrollment.
SECRETS_ENCRYPTION_KEYonce any org secret is usednone32 bytes as 64 hex characters. Encrypts the org secrets store. Changing it makes every stored secret unreadable.
EMAIL_ACTION_SECRETin productiona fixed dev valueAt least 32 characters. Signs one-click email links ("revoke this device"). Unset falls back to a public dev value and logs a warning. Not in render.yaml.
CRON_SECRETfor scheduled jobsnoneBearer token every /cron/* endpoint requires. Unset makes them answer 503. On Render it comes from the monark-cron-shared group.

Organization bootstrap

VariableRequiredDefaultWhat it does
INITIAL_ORG_SLUGon a fresh databasenoneSlug of the organization the api creates at boot when none exists. 2 to 60 lowercase letters, digits and hyphens.
INITIAL_ORG_NAMEon a fresh databasenoneDisplay name of that organization, up to 120 characters.
INITIAL_ORG_PRIMARY_COLORnononeHex colour (#RGB or #RRGGBB, quoted) that themes the whole UI. Falls back to BRANDING_PRIMARY.

Sign-in and webhooks

VariableRequiredDefaultWhat it does
AUTH_OAUTH_PROVIDERSnoemptyComma-separated social sign-in providers to offer: github, google, azure. Not in render.yaml or .env.example.
WEBHOOK_SECRETS_JSONnoemptyJSON object mapping webhook endpoint ids to their signing secrets.
WEBHOOK_SECRET_<endpointId>nononeOne endpoint's signing secret, read when WEBHOOK_SECRETS_JSON has no entry for it. Not in render.yaml.
MONARK_DEV_WEBHOOK_SECRETS_FILEno.cache/monark-webhook-secrets.json (dev)File that stores webhook signing secrets. Used by default outside production; in production only when set, with a warning.

Branding

All optional; an unset variable falls back to the neutral default shown. The web app needs the NEXT_PUBLIC_ mirror of each one it displays.

VariableDefaultWhat it does
BRANDING_APP_NAMEAppProduct name in the UI, page titles, emails.
BRANDING_TAGLINEA starter application.Tagline on the sign-in screen and in the page description.
BRANDING_SUPPORT_EMAILsupport@example.comSupport address shown to users.
BRANDING_TOTP_ISSUERAppName shown in authenticator apps. Changing it later forces re-enrollment.
BRANDING_FROM_EMAILApp <noreply@example.com>Sender for outbound mail when SMTP_FROM is unset.
BRANDING_PRIMARY#2563EBBrand colour when the organization has none.
BRANDING_ACCENT#4F46E5Second stop of gradient surfaces.
BRANDING_LOGO_SRC/logo.svgLogo path under services/web/public/, used before an org logo exists. Not in render.yaml.

Email

VariableRequiredDefaultWhat it does
SMTP_URLin productionnonesmtps://user:password@host:465 or smtp://…:587. Unset logs mail instead of sending it.
SMTP_FROMnoBRANDING_FROM_EMAILSender address, for example Monark <noreply@yourdomain.com>.

Error tracking

VariableRequiredDefaultWhat it does
SENTRY_DSNnononeTurns on server error reporting. Unset is a no-op.
SENTRY_ENVIRONMENTnoNODE_ENVEnvironment tag. render.yaml sets production / staging.
SENTRY_RELEASEnoSentry's ownRelease tag.
SENTRY_TRACES_SAMPLE_RATEno0Share of requests traced for performance.

AI assistant

None of these are in render.yaml or .env.example. Restart the api after changing them.

VariableRequiredDefaultWhat it does
ANTHROPIC_API_KEYfor the AI assistantnoneRead on first use, not at boot. Unset makes assistant replies fail with 503.
CHAT_LLM_PROVIDERnoanthropicModel provider. Any other value fails with 503.
CHAT_LLM_MODELnoclaude-sonnet-4-5-20250929Model id.
CHAT_LLM_MAX_TOKENSno4096Maximum tokens per reply.
CHAT_ASSISTANT_NAMEnoChrysaAssistant's name across the deployment.

Public API

VariableRequiredDefaultWhat it does
PUBLIC_API_RATE_PER_SECONDno5Per-key token refill rate for /api/v1. Not in render.yaml.
PUBLIC_API_BURSTno20Per-key burst ceiling for /api/v1. Not in render.yaml.

Web app (services/web)

Set in services/web/.env locally and in the Vercel project. NEXT_PUBLIC_* values are compiled into the build, so changing one takes a redeploy.

VariableRequiredDefaultWhat it does
NEXT_PUBLIC_API_URLyesnoneBrowser-facing api origin. Also added to the Content-Security-Policy connect-src.
NEXT_PUBLIC_APP_URLyesnoneThe web app's own origin.
NEXT_PUBLIC_SUPABASE_URLyesnoneSupabase project URL for the browser.
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEYyesnoneSupabase publishable key for the browser.
SUPABASE_URLyesnoneSupabase project URL for server actions.
SUPABASE_SECRET_KEYyesnoneServer-only. Used by admin server actions such as uploading the organization logo. Never set it as NEXT_PUBLIC_SUPABASE_SECRET_KEY.
NEXT_PUBLIC_BRANDING_APP_NAME, _TAGLINE, _SUPPORT_EMAIL, _PRIMARY, _ACCENT, _LOGO_SRCnoas the api's BRANDING_*Browser mirrors of the branding variables. Keep them equal to the api's values.
NEXT_PUBLIC_SENTRY_DSNnononeTurns on browser and web-server error reporting.
NEXT_PUBLIC_SENTRY_ENVIRONMENTnoNODE_ENVEnvironment tag.
NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATEno0Browser trace sample rate.
SENTRY_TRACES_SAMPLE_RATEno0Web-server trace sample rate.
SENTRY_ORG, SENTRY_PROJECT, SENTRY_AUTH_TOKENnononeBuild-time source-map upload. A build without the token still succeeds.
NEXT_PUBLIC_AUTH_STORAGE_KEYnosb-app-auth-tokenName of the browser storage key holding the session.
MONARK_AUTH_GATE_DEBUGnounset1 logs which sign-in gate redirected a request.
PORTno3000Local pnpm dev port. Read from the shell, then services/web/.env.local, then services/web/.env.

Scheduled jobs (Render cron services)

Shared through the monark-cron-shared group (production) and monark-cron-shared-staging (staging).

VariableRequiredWhat it does
CRON_SECRETyesSame value as the api's CRON_SECRET.
API_URLyesThe api's public URL, for example https://monark-api.onrender.com.

Prisma CLI (packages/db/.env)

VariableRequiredWhat it does
DATABASE_URLyesSame as the api's. Read by prisma migrate and prisma studio.
DIRECT_URLyesSame as the api's.

Supabase CLI (root .env, local only)

The Supabase CLI resolves env(...) references in supabase/config.toml from its own environment or a .env in the folder you run it from. It doesn't read services/api/.env.

VariableWhat it does
SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID, _GITHUB_SECRETGitHub OAuth app credentials.
SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID, _GOOGLE_SECRETGoogle OAuth client credentials.
SUPABASE_AUTH_EXTERNAL_AZURE_CLIENT_ID, _AZURE_SECRETMicrosoft Entra ID app credentials.

CI and repo tools

VariableRead byWhat it does
SHADOW_DATABASE_URLpnpm check:migrationsThrowaway Postgres the migrations are replayed into.
RENDER_API_KEYdeploy-api.yml (Actions secret)Lets CI trigger Render deploys after a green run.
DOCS_SYNC_APP_CLIENT_ID, DOCS_SYNC_APP_PRIVATE_KEYnotify-docs.yml (Actions secrets)GitHub App that tells the docs site to sync.
CODECOV_TOKENci.yml (Actions secret)Coverage upload to Codecov.
WEB_URLPlaywrightBase URL for end-to-end tests. Default http://localhost:3000.
E2E_USER_EMAIL, E2E_USER_PASSWORD, E2E_ADMIN_EMAIL, E2E_ADMIN_PASSWORDtools/seed-e2e-users.ts, e2e specsTest accounts. Passwords have no default.
E2E_FULL_STACKe2e specs1 runs the specs that need the full stack.

Related: Deploy checklist, Add a staging environment.