Operators

Environment variables

The core deployment contract is validated through @repo/env (Zod-validated via @t3-oss/env-nextjs). Provider packages also validate their selected provider's credentials. Boot fails fast if a required production variable is missing—you'll see a clear build error before traffic reaches a broken instance.

.env.local.example in the repo root is the canonical reference. This page mirrors it.

Required for any working deploy

VariableDescription
TURSO_DATABASE_URLlibSQL/Turso connection URL. libsql://... for Turso Cloud or file:./local.db for a local SQLite file. DATABASE_URL is a URL-only compatibility fallback.
TURSO_AUTH_TOKENTurso auth token. Empty or unset for local file-based DBs.
BETTER_AUTH_SECRET32+ random bytes (e.g. openssl rand -base64 32). Used to sign session cookies + magic links.
NEXT_PUBLIC_SAAS_URLSame as above; the NEXT_PUBLIC_ prefix exposes it to client-side code for cross-origin redirects.
NEXT_PUBLIC_MARKETING_URLPublic URL of the marketing site (e.g. https://brandbanta.com).
INNGEST_SIGNING_KEYFrom the Inngest Cloud dashboard. Used by Vercel to verify Inngest's incoming function calls.
INNGEST_EVENT_KEYFrom the Inngest Cloud dashboard. Used by our code to send events to Inngest.
CRON_SECRETA 32+ character random token; Vercel Crons automatically pass it via Authorization: Bearer ... to every /api/cron/* invocation.
OPENROUTER_API_KEYThe platform's shared OpenRouter key for free-tier scans. Without this, free-tier workspaces can't run scans at all (BYOK orgs are unaffected).
KEYRING_MASTER_KEY64-character hex key (32 bytes). AES-256-GCM key used to seal BYOK API keys at rest. Never rotate without re-encrypting existing rows — see below.

If any of these are missing, the saas app fails to start.

Email delivery (required for verification emails)

VariableDescription
MAIL_PROVIDEROne of resend, plunk, nodemailer, postmark, or mailgun. Production rejects console.
MAIL_FROMVerified sender address (e.g. BrandBanta <hello@brandbanta.com>).
Provider key(s)For example RESEND_API_KEY when using Resend. The production validator requires the selected provider's complete credentials.

Without these, sign-up still works in dev (verification is bypassed) but production users can't verify their email.

VariableDescription
SENTRY_DSNFrom the Sentry project settings. When unset, the SDK becomes a no-op — no errors crash.
SENTRY_AUTH_TOKENPersonal Access Token with Read & Write permission on Project + Release scopes. Used at build time to upload source maps.
SENTRY_ORGYour Sentry org slug.
SENTRY_PROJECTYour Sentry project slug.
NEXT_PUBLIC_WEB_VITALS_URLOptional endpoint to receive Web Vitals beacons. Leave unset to skip.

Storage (required for file uploads — avatars, brand logos)

VariableDescription
S3_ENDPOINTS3 endpoint URL (e.g. https://<account>.r2.cloudflarestorage.com for Cloudflare R2).
S3_REGIONRegion (e.g. auto for R2, us-east-1 for AWS).
S3_ACCESS_KEY_IDAccess key.
S3_SECRET_ACCESS_KEYSecret key.
NEXT_PUBLIC_AVATARS_BUCKET_NAMEBucket for user and organization avatars. Defaults to avatars.

Payments (parked behind feature flag until launch)

VariableDescription
NEXT_PUBLIC_BILLING_ENABLEDtrue to enable Stripe-based billing UI. Defaults to false.
STRIPE_SECRET_KEYFrom Stripe dashboard.
STRIPE_WEBHOOK_SECRETFrom Stripe webhook endpoint config.
PRICE_ID_PRO_MONTHLYProvider price identifier mapped to the Pro tier.
PRICE_ID_PRO_YEARLYProvider yearly price identifier mapped to the Pro tier.

Leave the Stripe variables unset until you're ready to launch billing — the rest of the app works without them.

Optional / feature-gated

VariableDescription
TAVILY_API_KEYEnables web-search grounding in the AI alias suggester. Without it, suggester falls back to LLM-only.
CSP_REPORT_ONLYProduction enforces CSP by default. Set true only for a time-bounded diagnostic rollback to Report-Only mode.
ENABLE_API_DOCStrue to expose /api/docs (OpenAPI Scalar UI) in production. Defaults to false; dev always shows it.
OPENTELEMETRY_API_VERSION_PINInternal pin to 1.9.0 in pnpm-workspace.yaml. Don't override unless you've audited the Sentry/Drizzle/Better-Auth peer tree.

Notes on rotation

  • BETTER_AUTH_SECRET — rotating invalidates all active sessions; users get logged out. Safe but disruptive.
  • KEYRING_MASTER_KEYDO NOT rotate without re-encrypting existing rows in org_api_credential. There's no rotation script today; a rotation is a manual job: decrypt every row with the old key, re-encrypt with the new key, swap the env var. Document this in your ops runbook if you ever need to rotate (e.g. suspected compromise).
  • CRON_SECRET — rotate by setting the new value in both Vercel env and vercel.json, deploy, then revoke the old. Brief overlap window is fine.
  • INNGEST_SIGNING_KEY — rotate via Inngest Cloud dashboard; follow their docs to avoid mid-flight event signing breaks.

See also

  • Deploying BrandBanta — full first-deploy checklist
  • Cron jobs — what each scheduled task does
  • .env.local.example in the repo — canonical list with inline comments

On this page