Skip to content

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 stale site_url value 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:

  1. Checkout the repo (resolves the apps/zensical/xo-compass/docs -> ../../../docs symlink)
  2. uv sync --package xo-compass — install the Zensical dependency for that workspace member
  3. cd apps/zensical/xo-compass && uv run zensical build --clean — build to public/ (per site_dir in zensical.toml)
  4. 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-built public/ 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.toml keeps site_dir = "public" — if Zensical's site/ 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:

gh workflow run deploy-xo-compass-vercel.yml


Verification

  1. Watch the run: gh run list --workflow=deploy-xo-compass-vercel.yml
  2. Visit https://bi-docs.xtendops.com and confirm the page reflects the latest docs/ content
  3. 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)