Supabase Setup Guide
Supabase Setup Guide
This guide covers everything needed to connect Surfc to Supabase for cross-device sync, including the migration workflow for keeping schema in sync across environments.
Prerequisites: Supabase CLI
Surfc uses the Supabase CLI to manage and scaffold migration files. Install it once as a
project devDependency (already listed in package.json):
npm installThe CLI is then available via npm scripts (e.g. npm run migrate:new). To confirm it is
installed:
npx supabase --version1. Create a Supabase project
- Go to supabase.com and sign in
- Click New project
- Choose a name (e.g.
surfc), set a database password, and select a region - Wait ~2 minutes for provisioning
2. Get your credentials
In your project dashboard, go to Settings → API:
| Value | Where to find it | .env variable |
|---|---|---|
| Project URL | Settings → API → Project URL | VITE_SUPABASE_URL |
| Anon / public key | Settings → API → anon key | VITE_SUPABASE_ANON_KEY |
| Service role key | Settings → API → service_role key | SUPABASE_SERVICE_ROLE_KEY (see below) |
| DB connection string | Settings → Database → Connection string (Session Mode) | DATABASE_URL (see below) |
Copy .env.example to .env and fill in VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY.
Never use the
service_rolekey in the app — it bypasses row-level security.
3. Developer tooling variables (local only)
Two additional variables are required to run npm run check:schema. Add them to your
local .env — they are intentionally absent from .env.example because they carry
elevated database privileges.
# .env additions — never commitSUPABASE_SERVICE_ROLE_KEY=eyJ... # Settings → API → service_role keyDATABASE_URL=postgresql://postgres.your-project:password@aws-0-region.pooler.supabase.com:5432/postgresFor DATABASE_URL, use the Session Mode pooler (port 5432) from:
Settings → Database → Connection string → Session mode
These variables are consumed only by scripts/check-schema.js (a Node.js tool, never
bundled into the browser app).
4. Apply migrations
Schema changes are managed as versioned SQL files in supabase/migrations/. Apply them
in order by pasting each file into the Supabase SQL Editor (Dashboard → SQL Editor →
New query → paste → Run):
| File | What it does |
|---|---|
0001_initial_schema.sql | Creates tables, RLS policies, storage bucket |
0002_notes_add_source.sql | Adds source column to notes |
0003_notes_add_source_ingest.sql | Adds source_id, source_meta, and index |
All migration files are idempotent (IF NOT EXISTS guards) — safe to re-run against an
existing database.
5. Verify the schema
After applying migrations, run the drift check to confirm the live schema matches the contract the app depends on:
npm run check:schemaA passing run prints:
[check-schema] ✓ All 30 checks passed — schema matches contract.A failing run names every issue:
[check-schema] 28 passed, 2 failed:
✗ [column] column "source_id" missing from table "notes" ✗ [column] column "source_meta" missing from table "notes"
[check-schema] Apply pending migrations via the Supabase SQL editor, then re-run.6. Configure email auth
By default Supabase requires email confirmation before sign-in. For development you may want to disable this:
- Go to Authentication → Providers → Email
- Toggle off Confirm email
7. Add environment variables to Netlify
If deploying via Netlify:
- Go to Site configuration → Environment variables
- Add
VITE_SUPABASE_URLandVITE_SUPABASE_ANON_KEY - Trigger a new deploy
DATABASE_URLandSUPABASE_SERVICE_ROLE_KEYare developer tools only — do NOT add them to Netlify.
8. Verify the full setup
- Run
npm run devlocally - The app should show a sign-in screen
- Create an account and sign in
- Add a note — check the Supabase dashboard under Table Editor → notes to confirm it appears
Adding new migrations
When the schema needs to change:
-
Create a new migration file using the CLI:
Terminal window npm run migrate:new -- describe_the_changeThis creates a timestamped file in
supabase/migrations/. -
Write the SQL (use
IF NOT EXISTS/IF EXISTSguards to keep it idempotent). -
Update
scripts/schema-contract.jsif you are adding a required table, column, policy, or resource that the app depends on. -
In your PR description, call out:
- The migration filename
- What it changes
- The steps to apply it (paste into SQL editor, then
npm run check:schema)
-
After merging, apply the migration to the production Supabase project before deploying the client that depends on it.
Migration notification hook
To be reminded whenever you stage a migration file, activate the project’s git hook:
npm run setup-hooksThis runs once per clone and prints a reminder in the terminal any time a migration is committed.
Free tier limits (as of 2026)
| Resource | Free limit | Surfc usage |
|---|---|---|
| Database size | 500 MB | Very low — text only |
| Storage | 1 GB | Moderate — one image per note |
| Auth users | Unlimited | — |
| API requests | Unlimited | — |
Storage is the main constraint if you photograph many passages. Each compressed note image is typically 200–400 KB, so the 1 GB limit accommodates roughly 2,500–5,000 images.