Launch

Deployment

Ship Kit to production. The web app targets Vercel; the database targets Supabase. Mobile, extension, and desktop each have their own pipeline.

Web App (Vercel)

1. Create the Project

Import the repo at vercel.com/new:

  • Root Directory: apps/web
  • Vercel detects Next.js and Turborepo automatically - no vercel.json needed

Or via CLI:

npm i -g vercel
vercel login
vercel   # from apps/web

2. Environment Variables

Set in the Vercel dashboard (same keys as .env.example):

# Database — Supavisor transaction pooler URL (:6543)
POSTGRES_URL=postgresql://...

# Auth
BETTER_AUTH_SECRET=generate-with-openssl-rand--base64-32
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...

# AI chat
AI_GATEWAY_API_KEY=...

# Avatar uploads (Supabase Storage)
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=...

The auth base URL derives from Vercel's built-in VERCEL_ENV / VERCEL_PROJECT_PRODUCTION_URL / VERCEL_URL - nothing to set. Adding the Supabase integration to the Vercel project populates the Postgres and Supabase vars for you.

3. Preview Deployments

The oAuthProxy plugin in packages/api/src/auth/auth.ts routes OAuth callbacks through the production URL, so GitHub login works on preview deployments without registering every preview domain.

4. Custom Domain

  1. Add your domain in the Vercel dashboard
  2. Update DNS as instructed
  3. SSL is automatic
  4. Update your GitHub OAuth app's callback URL

Database (Supabase)

  1. Create a production project at supabase.com

  2. Push the schema:

    # .env.production.local at the repo root with the production POSTGRES_URL
    pnpm db:push-remote

    drizzle-kit push connects directly (the config swaps :6543 for :5432 automatically).

  3. Create the avatars bucket - a public avatars bucket, no policies needed (writes go through /api/account/avatar with the service-role key). Local dev gets this from config.toml; hosted projects need it created in the dashboard.

RLS is already on for every table with no policies - deny by default. Authorization lives in tRPC; the server connection bypasses RLS as table owner.

Mobile (EAS)

Production builds need to know where the API lives:

// eas.json build profile env
{ "EXPO_PUBLIC_API_URL": "https://your-domain.com" }

Dev builds derive the URL from Metro. Then follow the standard EAS Build flow.

Extension and Desktop

pnpm -F @repo/extension build   # wxt build → .output/chrome-mv3
pnpm -F @repo/desktop build     # electron-vite build; package with electron-builder

Upload the extension to the Chrome Web Store; distribute desktop builds per electron-builder.yml.

CI/CD

Vercel deploys on push once the repo is connected - previews per PR, production on main. Schema pushes stay manual (pnpm db:push-remote) or go in a workflow step with POSTGRES_URL as a secret:

- name: Push database schema
  env:
    POSTGRES_URL: ${{ secrets.POSTGRES_URL }}
  run: pnpm -F db drizzle:kit push --force

Run checks before merging:

pnpm lint && pnpm typecheck && pnpm test && pnpm build

Health Checks

The app ships a liveness endpoint at /api/health (apps/web/src/app/api/health/route.ts). Point your uptime monitor at it:

curl https://your-domain.com/api/health
# {"status":"ok"}

Rollback

vercel ls                          # List deployments
vercel rollback [deployment-url]   # Roll back the web app

drizzle-kit push has no down migrations - take a backup before risky schema changes:

pg_dump $POSTGRES_URL > backup_$(date +%Y%m%d_%H%M%S).sql

Supabase paid plans also keep automated backups.

Production Checklist

  • BETTER_AUTH_SECRET set and unique per environment
  • Separate GitHub OAuth apps for dev and prod (callback: https://your-domain.com/api/auth/callback/github)
  • POSTGRES_URL uses the transaction pooler (:6543) - the client is configured for it
  • Avatars bucket exists in the production Supabase project (no policies needed)
  • Uptime monitor on /api/health

Next Steps

  1. Monitoring - Set up monitoring and observability
  2. Production checklist - Review production best practices

On this page