Supabase setup

Supabase setup

ClientNest uses hosted Supabase (Postgres, Auth, Storage, RLS). Local supabase start / Docker is not part of the supported path.

Create or link a project

Preferred:

pnpm supabase login
pnpm supabase:setup

The script creates clientnest-dev if you have no project, links this folder, pushes supabase/migrations in filename order, writes .env.local, and sets the Auth site URL to http://localhost:3000.

Manual path:

  1. Create a project in the Supabase dashboard.
  2. SQL editor or pnpm supabase db push --linked for every file in supabase/migrations.
  3. Paste the project URL and anon key into .env.local.

What migrations create

AreaNotes
Auth identitiesprofiles rows are created from Auth users
Workspaceworkspaces, memberships, invitations
Agency recordsclients, contacts, projects, milestones, tasks
Filesfiles metadata + private project-files bucket
Brandingprivate workspace-logos bucket, PNG/JPEG/WebP, no SVG
Workflowdeliverables, comments, append-only approvals
Billing recordsinvoices and line items in USD cents — no Stripe
Activityactivity_events with internal / client visibility
Notificationsin-app rows; email is a fetch adapter

Row Level Security is enabled and forced on business tables. Do not turn it off.

Auth URLs

Dashboard → Authentication → URL configuration:

SettingLocalProduction
Site URLhttp://localhost:3000https://your-domain
Redirect URLshttp://localhost:3000/**https://your-domain/**

The app uses /auth/confirm as the PKCE callback. Password reset continues to /reset-password.

Email templates can stay on the Supabase defaults. Confirmation and recovery links must keep the {{ .ConfirmationURL }} (or token-hash) placeholder.

Email (Auth SMTP)

Password-reset and signup confirmation mail is Supabase Auth SMTP, not the Next.js app.

# PowerShell
$env:RESEND_API_KEY='re_your_key'
pnpm supabase:smtp

Until you verify a domain in Resend, the From address is onboarding@resend.dev and delivery is limited to the Resend account email.

In-app notification email is separate: the same RESEND_API_KEY in .env.local / Vercel. No Resend SDK is installed. Missing key = in-app only.

Storage

Buckets come from migrations. You should not create them by hand.

BucketPublicPath shape
project-filesNo{workspace_id}/{project_id}/{file_id}
workspace-logosNo{workspace_id}/logo

Downloads go through /app/files/[id]/download (60-second signed URL) after an RLS check. Do not expose the service role to mint URLs in the browser.

Seed

pnpm supabase:seed
pnpm demo:files

seed.sql is idempotent. It restores Harbor Studio (fictional people only) and deletes extra Playwright rows in that workspace. It cannot create Storage objects; pnpm demo:files uploads the three Harbor files.

A public demo should use a separate project. From this repo (does not change .env.local):

pnpm supabase:demo

Isolation tests

pnpm rls:test

Needs a linked project and the service role in the environment. Expect RLS_OK. A failing negative case is a release blocker.