Go Live
Deploy BetterStarter to production in 2 minutes.
Deploy early, even before the app is "finished." First deploys are easiest when your app is still simple.
Quick Copy Checklist
Use this as your 2-minute launch checklist:
# 1) Create .env.production locally (gitignored)
cp .env.local .env.production
# 2) Edit .env.production for real production values
APP_BASE_URL=https://yourdomain.com
BETTER_AUTH_URL=https://yourdomain.com
BETTER_AUTH_SECRET=<long-random-secret>
DATABASE_URL=postgres://...
# 2.5) Add all feature-specific vars for enabled integrations
# Example: Stripe, Plunk/email, Google OAuth, analytics, storage, webhooks, etc.
# 3) Copy/import env vars from .env.production into hosting platform
# 4) Run production migration using .env.production
pnpm db:migrate:prod
# 5) Deploy on Vercel/Netlify and smoke testThe four variables above are the minimum for core auth + database. Most production apps need additional variables based on enabled features.
2-Minute Go-Live (One-Page Runbook)
Before You Start (30 seconds)
You need:
- App hosting: Vercel (recommended) or Netlify
- PostgreSQL: Neon (recommended) or Supabase
- Your production domain (example:
https://yourdomain.com)
Minute 1 — Configure Production
1) Prepare .env.production as source of truth
Create a production env file locally (it is ignored by git):
cp .env.local .env.productionThen edit .env.production with production values.
2) Add required environment variables in your host dashboard
Copy from .env.production and paste/import into your hosting platform:
APP_BASE_URL=https://yourdomain.com
BETTER_AUTH_URL=https://yourdomain.com
BETTER_AUTH_SECRET=<long-random-secret>
DATABASE_URL=postgres://...Notes:
APP_BASE_URLandBETTER_AUTH_URLshould match your final production URL.BETTER_AUTH_SECRETshould be a strong random secret.DATABASE_URLmust point to your production database (not local).
Then add all variables for every feature you have enabled. Common examples:
- Payments: Stripe keys + webhook secret
- Email: Plunk (or your provider) API key + sender values
- OAuth providers: client ID + client secret per provider (Google, GitHub, etc.)
- Observability/analytics: provider keys and host URL
- Storage or third-party APIs: access keys, bucket/region IDs, API secrets
If a feature works locally but fails in production, missing env vars are the most common cause.
3) Run production migrations
Run migration using .env.production:
pnpm db:migrate:prodThis local-file approach is common and fine for early-stage apps.
Preferred long-term workflow: run migrations from CI/CD or your hosting environment with production-only secrets, so production credentials are not handled from developer machines.
Minute 2 — Deploy and Verify
5) Deploy
Use the full platform guide if needed:
BetterStarter already includes vercel.json and netlify.toml, so both platforms can deploy with sane defaults.
6) Smoke test after deploy (60 seconds)
Open your production URL and confirm:
- Home page loads
- Sign up / sign in works
- Session persists after refresh
- A DB-backed page/action works
If auth fails, double-check that APP_BASE_URL and BETTER_AUTH_URL exactly match the deployed domain (including https).
Fast Troubleshooting
- Build failed: Recheck required env vars in the host dashboard.
- Feature works locally but not in production: Verify every feature-specific env var is set in hosting (Stripe/email/OAuth/etc.).
- Auth callback or cookie issues: URL mismatch between env vars and actual domain.
- DB connection errors: Wrong
DATABASE_URLor blocked network/access rules. - Schema errors: Run
pnpm db:migrate:prodagain and review migration SQL.
After You Go Live (Production DB Workflow)
For all future schema changes:
- Edit schema in
src/db/schema/ pnpm db:generateto create migration SQL- Review generated SQL in
drizzle/ - Back up production DB
pnpm db:migrate:prodto apply changes using.env.production
Avoid db:push in production. Use migrations (db:migrate) for safe, auditable changes.
BetterStarter outputs a standard Node.js server and also works on Railway, Render, Fly.io, and Cloudflare Workers.