Show navigationHide navigation
Multiple deploys (prod, staging, previews)
Each deployment resolves which Git branch serves public content independently. There is no shared cms/published.json. The pointer file path is cms/pointers/<build-id>.json on the pointer ref (see git.publishedPointerBranch in cms/octocms.config.ts), where <build-id> comes from the first set of: VERCEL_DEPLOYMENT_ID, VERCEL_BUILD_ID, GITHUB_RUN_ID, BUILD_ID, otherwise the literal local.
Resolution order#
- Per-build pointer file — JSON on the pointer branch (or
baseBranchifpublishedPointerBranchis unset) atgetPointerFilePath(). The payload is{ "branch": "<name>", "buildId": "<same id>" }.branchis what public reads use when that ref exists on GitHub. CMS_BRANCHenvironment variable — when the pointer file is missing, invalid, or names a branch that does not exist on GitHub.git.baseBranchfrom config (e.g.main).
When the pointer file is written#
- Publish in the CMS writes (or updates) the pointer for this build. The header branch selector only changes where saves go (the
cms-active-branchcookie); it does not change what the public site reads until you click Publish.
Environment variables#
| Variable | Purpose |
|---|---|
CMS_BRANCH | Fallback branch when no valid pointer override exists. Ignored if the branch does not exist on the remote. |
VERCEL_DEPLOYMENT_ID | Preferred build id for the pointer filename (Vercel). |
VERCEL_BUILD_ID | Second choice for build id (Vercel). |
GITHUB_RUN_ID | Build id in GitHub Actions. |
BUILD_ID | Set in CI or any host so each deploy gets a distinct pointer file when Vercel vars are absent. |
| (none) | Pointer path uses local — fine for a single dev machine; set BUILD_ID if several environments would otherwise share the same id. |
Branch picker#
Open the menu from the branch chip in the admin header on any /cms screen (including while still on main and before editing content). The list is the base branch plus open pull requests labelled cms-update whose head branch is under cms/*. The first action is Create new branch. The configured publishedPointerBranch is never shown in the list so editors do not select it by mistake.
Recipes#
Production (Vercel) — VERCEL_DEPLOYMENT_ID is set automatically; optional CMS_BRANCH=main. Use Publish to point public traffic at a branch for this deployment.
Staging — set a unique BUILD_ID (or run on a CI that sets GITHUB_RUN_ID) per environment so pointer files do not collide with production.
PR preview — each Vercel preview deployment gets its own deployment id, so preview pointers stay isolated.
Migration from cms/published.json#
That path is no longer read. Set CMS_BRANCH to your previous default, or use Publish once so the pointer file exists on the pointer branch for this build.
See also Editorial workflow.