Repository navigation
Deployment
The Hub deploys to Vercel with its database on Neon, and every pull request gets a live preview with its own isolated database branch. This page covers the pipeline end to end — what deploys where, what the preview actually proves, and the runbook for the things that go wrong.
flowchart TB
subgraph GitHub
PR[Pull request]
Main[main branch]
end
subgraph CI["GitHub Actions"]
Verify["verify.yml<br/>lint · build · tests · MCP smoke · types drift"]
NeonPrev["neon-preview.yml<br/>branch pr-N · migrate · seed"]
end
subgraph Vercel
Preview["Preview deployment<br/>per-PR URL"]
Prod["Production<br/>youngo-hub.vercel.app"]
end
subgraph Neon["Neon"]
PRBranch["pr-N branch<br/>(schema + seeded data)"]
ProdBranch["production branch"]
end
PR --> Verify & NeonPrev
NeonPrev --> PRBranch --> Preview
Verify --> Preview
Main --> Prod --> ProdBranch
Two things run on every PR in parallel: verify.yml proves the code (lint, build, integration tests on a Docker Postgres, the MCP handshake, a types-drift check that committed payload-types.ts matches the collections), and neon-preview.yml proves the schema against the real Neon stack — it creates a pr-<number> branch, runs npm run migrate, and hands the preview deployment its own database.
A preview is only as useful as its isolation, and the pipeline is built to provide it:
- Its own Neon branch — migrations run against a copy of the schema, so a breaking migration fails in CI rather than on the shared preview.
-
EMAIL_RECIPIENT_ALLOWLISTset — preview environments can send mail, but only to a defined list, so a test notification never reaches a real member. -
NEXT_PUBLIC_HUB_DEMOon — the UI marks the deployment as demo so nobody mistakes seeded content for real governance. - The branch is torn down when the PR closes (
pull_request.closed→ cleanup job), so previews don't leak databases.
Production is the main branch on the existing Vercel youngo-hub project — do not create a second Vercel project. Migrations run as part of the deploy flow against the production Neon branch. The ordering that keeps deploys safe:
- Merge to
main— Vercel builds and deploys. -
npm run migrateagainst the productionDATABASE_URL— either via the deploy hook or manually withpayload migratepointed at production. - Verify
/api/health and spot-check a real flow.
Migrations are designed to be backwards-compatible within a deploy — schema changes that would break the currently-running code should be split across deploys (expand first, contract after the code using the old shape is gone). This is the standard expand-and-contract discipline; the migration history shows it in practice.
Preview database is stale or broken. Close and reopen the PR — the cleanup/recreate cycle gives it a fresh branch. Or neonctl branches delete pr-N and push an empty commit.
A migration failed partway. Migrations run in a transaction where possible, so a failure usually leaves the database untouched. Check payload_migrations for what applied, fix the file, re-run npm run migrate.
Notifications aren't arriving in preview. Check the outbox endpoint first — rows in queued mean the cron drain isn't firing (Vercel cron needs to be configured per environment); rows in failed carry the SMTP error.
A member lost access after deploy. Almost always a record whose ends_at passed, or a migration that changed role strings — check unmappedRecords in their access profile.
Rollback. Vercel keeps previous deployments — promote the last good one from the dashboard. If a migration already ran, roll back code first, then assess whether the migration's down() needs to run; down scripts are maintained precisely for this case.
- One Vercel project, one production Neon project — preview isolation is per-branch, not per-service.
- The MCP content service deploys separately (it's a separate process, not part of the Next.js app) with its own
MCP_TOKEN. - No deploy step prints secrets or reset URLs —
PRINT_ADMIN_RESET_URLSis an emergency opt-in for bootstrap only.