Docs Site Deployment (Vercel)¶
Date: 2026-06-30
Status: Active
Prerequisite: None — read this before touching .github/workflows/deploy-xo-compass-vercel.yml or the Vercel project settings.
Overview¶
The platform documentation site (docs/ content, built by apps/zensical/xo-compass) deploys to
production at https://bi-docs.xtendops.com (Vercel project xo-data-mkdocs) via GitHub Actions.
There is no vercel.json in the repo — the Vercel project itself has no install/build command
configured, so it relies on zero-config "Other" framework detection, which only auto-serves a
top-level public/ directory. Zensical's build output dir defaults to site/ — zensical.toml
overrides this with site_dir = "public" to match what Vercel actually looks for (the same reason
the legacy mkdocs workflow used mkdocs build --site-dir public). The CI workflow does the full
build and uploads that public/ directory directly.
https://xo-data.vercel.app/is not the live domain — it's a stalesite_urlvalue that was never an actual alias for this project. Don't use it for verification.
apps/material-mkdocs is the predecessor of this site. Its deploy workflow
(deploy-mkdocs-vercel.yml) is kept as a manual-only rollback path (workflow_dispatch) and will
be removed along with the app itself after one sprint of stable xo-compass deploys. See
issue #1165.
How It Works¶
.github/workflows/deploy-xo-compass-vercel.yml runs on every push to main that touches
docs/** or the xo-compass app config, plus workflow_dispatch for manual runs:
- Checkout the repo (resolves the
apps/zensical/xo-compass/docs -> ../../../docssymlink) uv sync --package xo-compass— install the Zensical dependency for that workspace membercd apps/zensical/xo-compass && uv run zensical build --clean— build topublic/(persite_dirinzensical.toml)cd apps/zensical/xo-compass && npx vercel --prod— upload the directory to the existing Vercel project; since the project has no build command configured, Vercel serves the already-builtpublic/output as-is (zero-config static deploy)
Prerequisites Checklist¶
- GitHub repository secrets configured:
VERCEL_TOKEN,VERCEL_ORG_ID,VERCEL_PROJECT_ID(shared with the legacy mkdocs workflow — same Vercel project, same domain) - Vercel project's Root Directory / Output Directory left as default ("Other" framework,
no build command) — the workflow supplies a fully built
public/directory, so Vercel must not try to rebuild it remotely -
zensical.tomlkeepssite_dir = "public"— if Zensical'ssite/default is restored, the deploy goes blank/404 again
Triggering a Deploy¶
Automatic: push to main with changes under docs/**, apps/zensical/xo-compass/zensical.toml,
or apps/zensical/xo-compass/pyproject.toml.
Manual:
Verification¶
- Watch the run:
gh run list --workflow=deploy-xo-compass-vercel.yml - Visit
https://bi-docs.xtendops.comand confirm the page reflects the latestdocs/content - Spot-check a few previously shared top-level URLs (e.g.
/decisions/,/guides/) to confirm no broken links from the old mkdocs site
Troubleshooting¶
| Symptom | Likely Cause |
|---|---|
Deploy succeeds in CI but bi-docs.xtendops.com 404s |
Build output dir doesn't match what Vercel's zero-config detection serves (public/) — confirm zensical.toml has site_dir = "public" and the workflow's build step actually produced a public/ directory before the vercel upload step |
| Vercel deploy succeeds but shows old/blank content | Project has a build command configured remotely and is ignoring the pre-built public/ — check Vercel project's Build & Development Settings, clear any configured Build Command |
zensical build fails with missing docs/ |
Symlink didn't resolve — confirm actions/checkout ran with default symlink support (Linux runners handle this natively) |
| Both mkdocs and xo-compass deploys fire on the same push | deploy-mkdocs-vercel.yml should be workflow_dispatch-only; if it has a push trigger again, someone re-enabled it — revert |
Retiring apps/material-mkdocs¶
After one sprint of stable xo-compass deploys:
1. Delete apps/material-mkdocs/ and .github/workflows/deploy-mkdocs-vercel.yml
2. Remove apps/material-mkdocs from the [tool.uv.workspace] members in the root pyproject.toml
3. Update snowflake-object-inventory.md /
dbt-model-registry.md only if affected (unlikely — docs-only change)