Command Inbox
Reference

Environment variables

Complete environment variable reference with validation rules

All variables are validated in src/lib/env.ts at server boot. Optional blank strings are coerced to undefined.

NODE_ENV

PropertyValue
Type"development" | "test" | "production"
Default"development"
Phase0

DATABASE_URL

PropertyValue
Typestring (min 1 char)
RequiredYes
Phase0
Examplepostgresql://user:pass@ep-xxx.pooler.neon.tech/neondb?sslmode=require

Neon pooled connection string recommended for serverless.

CORSAIR_KEK

PropertyValue
Typestring (min 1 char)
RequiredYes
Phase0
Generateopenssl rand -base64 32

Corsair key-encryption key. Not CORSAIR_SECRET. Must remain stable after corsair:setup.

GOOGLE_CLIENT_ID

PropertyValue
Typestring
RequiredYes
Phase0
ValidationMust end with .apps.googleusercontent.com

Shared by Better Auth and Corsair Gmail/Calendar plugins.

GOOGLE_CLIENT_SECRET

PropertyValue
Typestring (min 1 char)
RequiredYes
Phase0

BETTER_AUTH_URL

PropertyValue
TypeURL string
Defaulthttp://localhost:3000
Phase0

Canonical app URL for Better Auth. Production: https://command-inbox.sayantanbal.in

APP_URL

PropertyValue
TypeURL string
RequiredNo
DefaultFalls back to BETTER_AUTH_URL
Phase0

Used for Corsair OAuth redirects and webhook base URL. Set to ngrok HTTPS URL during local webhook development.

Helper: getAppUrl() returns APP_URL ?? BETTER_AUTH_URL.

BETTER_AUTH_SECRET

PropertyValue
Typestring (min 32 chars)
RequiredPhase 1 (sign-in)
Generateopenssl rand -base64 32

Enforced by assertPhase1Env() when auth is used.

BETTER_AUTH_API_KEY

PropertyValue
Typestring (non-empty)
RequiredNo
Phase1

Optional — @better-auth/infra Dash/Sentinel hosted features only.

GOOGLE_GENERATIVE_AI_API_KEY

PropertyValue
Typestring (non-empty)
RequiredOne of two AI keys for Phase 2
Phase2

Powers Gemini chat (gemini-2.5-flash) and embeddings (text-embedding-004).

OPENAI_API_KEY

PropertyValue
Typestring (non-empty)
RequiredOne of two AI keys for Phase 2
Phase2

Default provider — GPT-5 Nano + text-embedding-3-small.

GMAIL_PUBSUB_TOPIC

PropertyValue
Typestring (non-empty)
RequiredNo (required for webhooks)
Phase2
Formatprojects/<project-id>/topics/<topic-name>

PUSHER_APP_ID

PropertyValue
Typestring (non-empty)
RequiredNo
Phase2

Server-side Pusher Channels app ID.

PUSHER_KEY

PropertyValue
Typestring (non-empty)
RequiredNo
Phase2

Server-side Pusher key.

PUSHER_SECRET

PropertyValue
Typestring (non-empty)
RequiredNo
Phase2

Server-side Pusher secret.

PUSHER_CLUSTER

PropertyValue
Typestring (non-empty)
RequiredNo
Phase2
Exampleus2

NEXT_PUBLIC_PUSHER_KEY

PropertyValue
Typestring (non-empty)
RequiredNo
Phase2

Browser-exposed Pusher key — must match server app.

NEXT_PUBLIC_PUSHER_CLUSTER

PropertyValue
Typestring (non-empty)
RequiredNo
Phase2

Must match PUSHER_CLUSTER.

CRON_SECRET

PropertyValue
Typestring (non-empty)
RequiredNo (required for send-later)
Phase3+
Generateopenssl rand -base64 32

Bearer token for POST /api/cron/process-due.

Phase assertion helpers

FunctionThrows when
assertPhase1Env()BETTER_AUTH_SECRET missing
assertPhase2Env()Both AI keys missing

Client exposure rules

Only NEXT_PUBLIC_* variables are available in browser bundles. Never import @/lib/env from client code — the module uses import "server-only".