Branching & deployment
Supabase branching
Section titled “Supabase branching”Two shared Supabase projects:
| Project | Purpose |
|---|---|
movement-mapping-dev | Shared dev project. CI applies merged migrations here. |
movement-mapping-prod | Production. Only CI applies migrations here. |
Project-level provisioning (not covered by migrations)
Section titled “Project-level provisioning (not covered by migrations)”supabase/migrations/*.sql only reaches the database. A handful of settings
live at the Supabase project level instead, and a brand-new project (or a
recreated one) starts without them:
- PostgREST’s exposed-schema list defaults to
public, graphql_public—appandnetworkare invisible to the API until added, regardless of RLS. - The Auth
site_urldefaults tohttp://localhost:3000on a new project — it’s what{{ .SiteURL }}resolves to in Auth email templates (confirmation, magic link), so without setting it, confirmation emails link back to localhost no matter what environment sent them. - The Auth redirect allow-list starts empty, so
/auth/confirmand/auth/callbackare rejected as invalid redirect targets.
scripts/supa-configure-project.sh [project-ref] sets all three (idempotent),
and runs automatically from scripts/supa-first-run.sh whenever a project has
no migrations yet — so this covers the local shared/parent project by default.
It must also be run once against movement-mapping-dev and
movement-mapping-prod when each is first provisioned, since CI only ever
applies migrations there, never this script. Run it from a checkout with no
local .env (or a temporarily moved-aside one) — the script re-sources
.env if present, which silently overrides SUPABASE_PROJECT_REF/SITE_URL
passed on the command line:
SUPABASE_PROJECT_REF=<dev-or-prod-ref> SITE_URL=<its-public-url> \ ./scripts/supa-configure-project.shOne more setting needs a decision before it can be scripted: Auth email
template customisation (the “Confirm signup” and “Magic Link” templates) is
blocked by Supabase on the free tier without a custom SMTP provider — without
it, both templates keep the default {{ .ConfirmationURL }} link instead of
the token_hash-based link /auth/confirm expects, so email confirmation and
magic-link sign-in silently fail (you land back on /setup or /login
logged out).
This project uses Resend as the custom SMTP provider. Once you have a
domain verified in Resend and an API key, set RESEND_API_KEY and
SMTP_SENDER_EMAIL (optionally SMTP_SENDER_NAME) and re-run
scripts/supa-configure-project.sh — it configures Resend as the project’s
SMTP relay and pushes the branded templates from supabase/templates/
(confirmation.html, magic-link.html) via the Management API. Without
those variables set, the script skips this step and prints the template text
to set by hand instead (Dashboard → Authentication → Email Templates).
Render deployment
Section titled “Render deployment”Deployment is config-as-code in render.yaml, with two services pinned to the
EU (Frankfurt) region:
- a web service for
apps/app(the TanStack Start Node server), and - a static site for
apps/docs(built and published fromapps/docs/dist).
There is no manual dashboard configuration; secrets are set in Render’s environment, not committed. See Environment variables.
.github/workflows/ci.yml— on PRs and pushes tomain: frozen-lockfile install,biome check, typecheck, build of both apps, and a Socket.dev supply-chain check..github/workflows/db.yml— applies migrations tomovement-mapping-devon merge tomain, and promotes them tomovement-mapping-prodon release..github/workflows/supabase-branch-cleanup.yml— deletes a git branch’s Supabase branch when the git branch is deleted.