Skip to content
Documentation menu

Supabase runbook (condensed)

The full copy-pasteable version lives in the repo at product-docs/05_RUNBOOK.md. This is the condensed operator summary: demo deploy → Supabase + real providers in about an hour.

StepWhatBudget
1Push repo to GitHub5 min
2Vercel import, DEMO deploy10 min
3Supabase project + migrate + seed15 min
4Flip env to postgres + provider keys, redeploy10 min
5Enable durable run execution10 min
6Post-swap checklist8 min

1–2. GitHub + demo deploy

Push the repo (git remote add origin … && git push -u origin main), import it into Vercel (Next.js auto-detected, all defaults). Env for the demo deploy: DEMO_MODE=1, SESSION_SECRET (openssl rand -base64 32), OPERATOR_EMAIL, OPERATOR_PASSWORD. Deploy, then verify /api/health shows "demoMode":true. This deploy is also your one-minute rollback target.

3. Supabase

Create a project and copy both connection strings: the transaction pooler (port 6543) becomes DATABASE_URL; the direct connection (port 5432) becomes DIRECT_URL. Locally set DB_DRIVER=postgres plus both URLs, then:

pnpm exec drizzle-kit migrate   # runs against DIRECT_URL, TLS forced by drizzle.config.ts
OPERATOR_EMAIL=you@… OPERATOR_PASSWORD=… pnpm seed

Migrations go through DIRECT_URL only: DDL through the transaction pooler is unreliable (it multiplexes sessions across backends). The app itself always uses the pooled URL.

4. Flip the deploy

In Vercel env vars: remove DEMO_MODE; add DB_DRIVER=postgres, DATABASE_URL, DIRECT_URL, DATAFORSEO_LOGIN, DATAFORSEO_PASSWORD, PERPLEXITY_API_KEY. Redeploy. Verify /api/health shows "driver":"postgres" and Settings → Engines shows every engine configured.

5. Run execution

Immediately: run pnpm worker anywhere with the Supabase env — it claims queued runs safely (90-second stale-claim protocol) and executes them. Durable end state: wire the Vercel Workflows entrypoint (app/workflows/run.ts, one step per batch around the same shared executor) — the workflow package is installed; see runbook step 5 for exactly where to flip.

6. After the swap

  • Sign in as your real operator; create your first real agency. There is no demo data to clean up — pre-Supabase data was in-memory/local and disposable by design.
  • RLS: tables ship with RLS disabled; isolation is app-layer (session-scoped DAL, e2e-tested). Never add supabase-js or expose the anon key. The dashboard linter will complain — acknowledge it, don't enable RLS (without policies it adds no protection).
  • Demo-period access requests: retrieve ACCESS_REQUEST log lines from Vercel Logs now — Hobby retention is short. From here on, requests persist in the database and appear at /requests.
  • Custom domain: add it in Vercel; nothing in the app hardcodes a URL.
  • Password recovery: Forgot your password? on the sign-in card emails a one-hour, single-use link (and still asks for a code when the second sign-in step is on). pnpm user:set-password <email> is the backstop for a lost mailbox, a lost authenticator plus recovery codes (--reset-mfa), or a deployment with no email key set.
  • Email is optional. Set RESEND_API_KEY and EMAIL_FROM with a sending domain verified in Resend; leave them unset and nothing is sent, with every surface falling back to a stated alternative. Setting the key adds a sub-processor, which the security page lists.

Rollback: re-add DEMO_MODE=1, redeploy — back on the self-contained demo while Supabase keeps your data untouched.