Validated at build time by src/env.js — a production build fails fast on
a missing required variable.
| Variable | Required in prod | Notes |
|---|---|---|
BETTER_AUTH_SECRET |
✅ (min 32 chars) | openssl rand -base64 32 |
BETTER_AUTH_URL |
✅ | Canonical origin, e.g. https://app.example.com. OAuth redirect URIs, trusted origins, and absolute URLs derive from it (src/server/config.ts). |
DATABASE_URL |
✅ | Postgres (Neon/Supabase/RDS). Use a pooled connection string on serverless. |
BETTER_AUTH_GOOGLE_CLIENT_ID / _SECRET |
✅ for Google features | From the verified Google Cloud project. |
CORSAIR_KEK |
✅ for Gmail/Calendar | openssl rand -base64 32. Encrypts per-tenant Google tokens at rest. Losing it invalidates stored integration credentials. |
GOOGLE_GENERATIVE_AI_API_KEY |
✅ for AI features | Gemini key. |
BETTER_AUTH_GITHUB_CLIENT_ID / _SECRET |
optional | GitHub sign-in. |
WEBHOOK_PUBLIC_URL |
optional | Set to BETTER_AUTH_URL in production to enable realtime push. |
GMAIL_PUBSUB_TOPIC |
optional | projects/<id>/topics/gmail-push; see .env.example for one-time Pub/Sub setup. |
WEBHOOK_VERIFICATION_TOKEN |
recommended with webhooks | openssl rand -hex 16; verified on every webhook delivery. |
There are no localhost assumptions in the codebase: every absolute URL
comes from appUrl() in src/server/config.ts (BETTER_AUTH_URL →
VERCEL_URL → localhost dev fallback).
In the OAuth client for the production deployment:
- Authorized redirect URI:
<BETTER_AUTH_URL>/api/auth/callback/google(and/api/auth/callback/githubon GitHub's side if enabled). - Authorized JavaScript origin:
<BETTER_AUTH_URL>. - Enable the Gmail API and Google Calendar API.
- Complete OAuth verification before public launch — see
docs/google-oauth-verification.md.
Schema is managed with drizzle-kit. For production prefer generated migrations over push:
pnpm db:generate # generate SQL migrations from src/server/db/schema.ts
pnpm db:migrate # apply- Health check:
GET /api/health— 200 ({"status":"ok"}) when the database is reachable, 503 otherwise. Point uptime monitoring here. - Logging: all server logs are single-line JSON in production
(
src/server/logger.ts); pipe Vercel log drains to your aggregator. Wire an error monitor (e.g. Sentry) viasetErrorReporter()once at startup — everylog.errorflows through it. - Security headers (HSTS, nosniff, frame-deny, referrer/permissions
policy) are set globally in
next.config.js. - Webhooks: Gmail/Calendar watch channels auto-renew lazily
(
src/server/corsair/watch.ts) whenever a user is active; no cron needed.
-
pnpm check(lint + typecheck) andpnpm buildpass. - All required env vars set in Vercel (Production environment).
-
BETTER_AUTH_URLmatches the custom domain exactly (https, no trailing slash). - Database migrated; connection string is the pooled variant.
-
/api/healthreturns 200 on the production URL. - OAuth round-trip works on production: sign in with Google, connect
Gmail, connect Calendar, disconnect from
/settings. - Google OAuth verification submitted/approved (see the companion doc).