Command Inbox
Developer Guide

Environment variables

Phase-gated configuration — what to set and when

Command Inbox validates environment variables at boot via Zod in src/lib/env.ts. Blank optional vars are treated as undefined.

For the complete reference with validation rules and examples, see Environment reference.

Phase 0 — Infrastructure (required to boot)

VariableRequiredNotes
DATABASE_URLYesNeon pooled Postgres URL with ?sslmode=require
CORSAIR_KEKYesBase64 encryption key — openssl rand -base64 32
GOOGLE_CLIENT_IDYesMust end with .apps.googleusercontent.com
GOOGLE_CLIENT_SECRETYesOAuth client secret
BETTER_AUTH_URLYesDefault http://localhost:3000
APP_URLNoDefaults to BETTER_AUTH_URL; use for webhooks/OAuth

Phase 1 — Authentication

VariableRequiredNotes
BETTER_AUTH_SECRETYes for sign-inMin 32 chars — openssl rand -base64 32
BETTER_AUTH_API_KEYNoBetter Auth infra/Dash only

assertPhase1Env() throws if BETTER_AUTH_SECRET is missing when auth routes run.

Phase 2 — AI, webhooks, realtime

VariableRequiredNotes
GOOGLE_GENERATIVE_AI_API_KEYOne of twoGemini classify + embed
OPENAI_API_KEYOne of twoOpenAI chat + embed (default provider)
GMAIL_PUBSUB_TOPICFor webhooksprojects/<project>/topics/<name>
PUSHER_APP_IDOptionalServer-side Pusher
PUSHER_KEYOptionalServer-side
PUSHER_SECRETOptionalServer-side
PUSHER_CLUSTEROptionale.g. us2
NEXT_PUBLIC_PUSHER_KEYOptionalBrowser client
NEXT_PUBLIC_PUSHER_CLUSTEROptionalMust match server cluster

assertPhase2Env() requires at least one AI key for classification, drafts, search, and agent.

Without Pusher, inbox falls back to 5-second polling.

Phase 3+ — Cron

VariableRequiredNotes
CRON_SECRETFor send-laterBearer token for /api/cron/process-due

Generate: openssl rand -base64 32

Production overrides

VariableLocalProduction
BETTER_AUTH_URLhttp://localhost:3000https://command-inbox.sayantanbal.in
APP_URLngrok URL in devSame as production app URL
DATABASE_URLNeon dev branchNeon production branch

Client-safe variables

Only NEXT_PUBLIC_* vars are exposed to the browser. Never import @/lib/env from client components — it uses server-only and will break client bundles or leak validation errors.

Restart after changes

After editing .env.local, restart the dev server. Next.js does not hot-reload env changes.