Documentation Index
Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
Use this file to discover all available pages before exploring further.
Version: 1.0.0
Last Updated: 2026-04-24
Owner: Platform / Infra
This runbook locks in the canonical mapping of GitHub branches → Vercel projects → Supabase projects so that:
- Day-to-day PRs only touch the Dev environment.
- Promotions to live production are an explicit
prod → production release PR.
- Supabase Branching only spins up preview DBs in one Supabase project per PR (no more duplicated
Supabase Preview failures from two competing projects, as seen on PR #123/#124).
When this document conflicts with docs/development/supabase/SUPABASE_MULTI_ENV_SETUP.md or any in-dashboard setting screenshot, this document wins. Update both together.
1. Canonical mapping
| Tier | GitHub branch | Vercel project | Vercel project ID | Supabase project | Supabase project ref |
|---|
| Dev | prod (default) | encoreos_dev | prj_iMHAljBMLDQXONzL9g7XUHH6CzrP | Encore OS | zkgxozahyczcnzpwhbbf |
| Production | production | encoreos_prod | prj_NZTWEPkUXJ3jM51uh91Ty8Np9K7c | encore_os_prod | srcaoozjkrughebmbvfb |
Naming gotcha. The GitHub default branch is named prod, but it is the dev tier. The branch literally named production is the live production tier. This mismatch is intentional (preserves history) but easy to misread. Do not rename.
Frontend pairing is enforced at build time in vite.config.ts via the platform-managed VERCEL_PROJECT_ID system variable. Do not add user-defined Vercel env vars for VITE_SUPABASE_URL / VITE_SUPABASE_PUBLISHABLE_KEY (CI guards this via npm run check:no-vercel-env-config).
CLI/migrations pairing is captured in supabase/config.toml:
[remotes.dev] # paired with GitHub `prod` and Vercel encoreos_dev
project_id = "zkgxozahyczcnzpwhbbf"
[remotes.production] # paired with GitHub `production` and Vercel encoreos_prod
project_id = "srcaoozjkrughebmbvfb"
2. PR / deployment lifecycle
2.1 Feature work (default)
- Branch off
prod: git checkout -b cursor/<task>-####.
- Open a PR with base =
prod.
- On open, the following side effects occur:
- Vercel
encoreos_dev builds a Preview Deployment, statically pinned to Supabase zkgxozahyczcnzpwhbbf.
- Supabase
Encore OS (zkgxozahyczcnzpwhbbf) Branching creates a per-PR preview DB and replays migrations. The Supabase Preview GitHub check reports its status.
- Vercel
encoreos_prod and Supabase encore_os_prod are not touched (see §3 for how this is enforced).
- Merge to
prod ⇒ Vercel encoreos_dev deploys to its production URL (the dev environment), and Supabase Encore OS is updated by a successful Branching deploy run.
- Open a release PR with head =
prod and base = production.
- On open, only the production tier is touched:
- Vercel
encoreos_prod builds a Preview Deployment.
- Supabase
encore_os_prod (srcaoozjkrughebmbvfb) Branching creates a per-PR preview DB.
- Merge ⇒ Vercel
encoreos_prod deploys to the live production URL; Supabase encore_os_prod Branching applies migrations to the live production DB.
Production is a one-way door. Do not direct-commit to production.
Canonical intent: The Supabase Preview check on a prod → production PR replays supabase/migrations against the production-tier preview database (srcaoozjkrughebmbvfb). Treat that preview as the primary validation signal for “what will run in prod.”
Recommended sequence:
- Open the release PR (
prod → production) and wait until Supabase Preview (and your usual Vercel preview checks) are green.
- GitHub branch protection: mark the Supabase GitHub check as a required status on
production, so merges are blocked when preview fails.
- Merge the PR on GitHub. With Deploy to production enabled in the Supabase GitHub integration (see §3.2), Branching applies the same migration chain to the live production database.
- Deploy Supabase (production) workflow (
.github/workflows/supabase-deploy-prod.yml) still runs supabase db push --yes on push to production as a reconcile with the repo. Keep migration files identical to what Branching replays so both paths stay aligned.
- Break-glass: if migrations were applied only via the Supabase Dashboard (or another one-off path) and
db push would be redundant or risky, run the same workflow manually with skip_db_push enabled so Edge Functions and other steps can still run without a second push.
Single writer rule: Do not routinely apply different SQL manually and then db push different content. One owner per promotion: repo migrations + Branching replay + optional CI db push, or documented break-glass only.
3. Supabase dashboard configuration (operator)
Both Supabase projects use the same GitHub repository (Encore-OS/encoreos) but must each declare a different Production Branch and have appropriate Branching scope so previews don’t collide.
For each project below, open Supabase Dashboard → Project Settings → Integrations → GitHub Integration → Manage.
3.1 Encore OS (zkgxozahyczcnzpwhbbf) — Dev tier
| Field | Value |
|---|
| Repository | Encore-OS/encoreos |
| Supabase directory | supabase |
| Production branch | prod |
| Automatic branching | ON |
| Supabase changes only | ON (recommended — only create preview DBs when supabase/** changes) |
| Deploy to production | ON (so merges to prod deploy migrations to the dev DB) |
Effect: every PR opened against prod gets exactly one preview DB inside this project. Today the Production Branch on this project is incorrectly prod already (verified via MCP list_branches: default branch row has git_branch: "prod"), so the only required change here is to confirm settings match the table.
3.2 encore_os_prod (srcaoozjkrughebmbvfb) — Production tier
| Field | Value |
|---|
| Repository | Encore-OS/encoreos |
| Supabase directory | supabase |
| Production branch | production |
| Automatic branching | OFF (recommended) — only create a preview DB when a release PR targets production |
| Supabase changes only | ON |
| Deploy to production | ON |
Effect: regular feature PRs targeting prod will not create preview DBs in this project. Only the explicit prod → production release PR creates a preview DB here. This eliminates the duplicate Supabase Preview failure pattern observed on PR #123/#124, where a single feature PR triggered identical migration replay in both projects.
If “Automatic branching = OFF” turns out to be too restrictive (e.g. you want a smoke deploy on every release-candidate PR), set it to ON + “Supabase changes only = ON” so only PRs that touch supabase/** and target production consume a production-tier preview DB.
3.3 Verification
After applying §3.1 and §3.2:
# Should list ONE non-default branch row per active PR base (excluding the
# default branch row itself), keyed to the GitHub branch the PR targets.
gh api /repos/Encore-OS/encoreos/pulls -q '.[] | {n: .number, base: .base.ref, head: .head.ref}'
Then in MCP / CLI:
Encore OS (zkgxozahyczcnzpwhbbf) list_branches should show default_branch_row.git_branch = "prod" and one row per PR targeting prod.
encore_os_prod (srcaoozjkrughebmbvfb) list_branches should show default_branch_row.git_branch = "production" and one row only when there is an open prod → production release PR.
4. Vercel dashboard configuration (operator)
For each Vercel project, open Vercel → Project → Settings → Git.
4.1 encoreos_dev (prj_iMHAljBMLDQXONzL9g7XUHH6CzrP)
| Field | Value |
|---|
| Connected repo | Encore-OS/encoreos |
| Production Branch | prod |
| Ignored Build Step | inherits vercel.json (ignoreCommand lives in repo) |
| Preview deployments | All branches except production (set Settings → Git → “Branch Tracking” or use vercel.json-side filter; see §4.3) |
4.2 encoreos_prod (prj_NZTWEPkUXJ3jM51uh91Ty8Np9K7c)
| Field | Value |
|---|
| Connected repo | Encore-OS/encoreos |
| Production Branch | production |
| Preview deployments | Only prod (release-candidate previews) |
4.3 Optional: prevent both Vercel projects from previewing the same PR
By default Vercel will deploy a Preview for every PR on a connected repo, regardless of which branch the PR targets. To restrict each project so a single PR only produces a preview in the matching project:
- In
encoreos_dev → Settings → Git → “Ignored Build Step”, keep the in-repo vercel.json ignoreCommand (already set). It will short-circuit identical builds.
- In
encoreos_prod → Settings → Git → “Branch Tracking”, set “Only deploy preview branches matching pattern” to prod. That stops it from building previews for arbitrary cursor/* branches.
Both Vercel projects share the same repo, but only the project whose Production Branch matches the PR’s base branch should build it. Branch Tracking patterns are the cleanest way to enforce that.
5. Repo-side guardrails
These already exist; the alignment relies on them staying in place.
| Guardrail | Where | What it enforces |
|---|
Static VITE_SUPABASE_* defines keyed by VERCEL_PROJECT_ID | vite.config.ts SUPABASE_PROJECTS + VERCEL_PROJECT_TO_SUPABASE | Vercel project → Supabase pairing cannot drift from this file |
[remotes.dev] / [remotes.production] | supabase/config.toml | CLI supabase link --project-ref targets are spelled out |
npm run check:no-vercel-env-config | scripts/ci/* (run by validate:governance) | Re-introducing user-defined Vercel env vars for Supabase URL/key fails CI |
audit:integration-contracts, audit:routes-navigation, audit:permissions, audit:breadcrumb-coverage | npm run validate:governance | Unrelated, but these all key off prod as the canonical baseline branch |
| Migration baseline | supabase/migrations/20260211182655_*.sql (2026-04 reconcile baseline) | Single source of truth for both Supabase projects’ schema; subsequent migrations must remain idempotent (see SUPABASE_RECONCILE_2026-04.md) |
6. One-time cleanup actions
After §3 and §4 are applied, perform these once:
- Close stale duplicate-tier PRs. PR #123 (
Gr-ux → production) and PR #124 (Gr-ux → prod) both exist for historical reasons. Once branching is realigned, decide which target is correct:
- If the change is dev-bound, keep PR #124 (
→ prod) and close PR #123.
- If it is also intended for live production, do not target
production directly from a feature branch; merge to prod first, then open a release PR prod → production.
- Re-run the Supabase Preview check on the surviving PR after §3 is applied. It should now run against only one Supabase project.
- Optional but recommended: delete or repurpose the legacy GitHub branch named
production if the team decides the dev/prod separation should be prod → main or develop → prod instead. Keep this document in sync if you do.
7. Failure-mode reference
| Symptom | Likely cause | Fix |
|---|
Same Supabase Preview check failure on two PRs sharing a head SHA | Both Supabase projects have Branching ON for the same Production Branch (or for branches that overlap) | Apply §3.2 — set encore_os_prod Production Branch to production and Automatic Branching = OFF |
| Vercel preview deploys to the wrong Supabase | vercel.json introduced env block, or someone re-added VITE_SUPABASE_URL to Vercel project env vars | Remove; CI’s check:no-vercel-env-config catches this. Pairing is enforced via VERCEL_PROJECT_ID in vite.config.ts |
Migration replay fails in preview with 42P07 relation already exists | Non-idempotent CREATE TABLE after the 2026-04 baseline | Add IF NOT EXISTS; precedent: PR #125 fix to pf_oauth_state |
| Two Vercel previews per PR | Both Vercel projects accept all branches | Apply §4.3 Branch Tracking pattern to encoreos_prod |
8. References