Skip to content

Docs site — build, mirroring, and editing rules

How docs.virdx.dev / docs.fra.virdx.dev are built (Astro + @cloudflare/nimbus-docs), how this knowledge repo is mirrored into it at build time, and why content changes belong here rather than in mono.

The VIRDX docs site (mono/apps/docs, Astro + @cloudflare/nimbus-docs) has two tabs — Documentation (product docs, live under /documentation/*) and Knowledge — both behind Cloudflare Access. It is served from two surfaces:

Introduced in mono#305 (feat/docs-knowledge-section).

This repo is mirrored in, not copied by hand

Content stays in this repo (virdx/knowledge), not mono, because agents can commit here freely while mono is review-gated. At build time, apps/docs/bin/sync-knowledge.ts pulls a checkout of this repo and normalizes it into Nimbus’s strict docs content collection:

  • frontmatter is reduced to title/description (+ sidebar.order);
  • the leading H1 is stripped (Nimbus renders the title from frontmatter — which is also why every concept doc here should carry a real H1: the nine sources/monthly-reports/*.md files that opened at ## with no H1 used to render with filename-derived titles like 01 2026_diffsim before this was fixed);
  • relative *.md links are rewritten to extensionless site URLs.

Only wiki/ and inbox/ are published. sources/ is deliberately not published — it’s legacy, superseded by wiki/ (see top-level index.md). Links from wiki/ into sources/ resolve to GitHub blob URLs instead of dead site routes.

The build is the interesting part: two repos, one image

docs is the first image built from two repos, and this knowledge repo changes far more often than mono does, so nothing in mono’s history moves just because knowledge content changed.

  • apps/docs/Containerfile does an unconditional COPY .knowledge/; the sync script reads it via KNOWLEDGE_PATH. No git credentials go inside the image build — whoever builds supplies the checkout.
  • GitHub Actions (Cloudflare Pages deploy) supplies it via actions/create-github-app-token@v2 against the existing org App — no new secret needed.
  • For the cluster image, apps/docs/deployments/build.sh submits an inline pipelineSpec (no stored Pipeline needed) that clones both repos, referencing the existing git-clone, check-image, and buildkit-build Tasks unchanged. git-clone hardcodes its destination to /workspace/source/repo, so the second checkout has to be an inline step — see the cluster SOP’s gotchas.
  • check-image’s idempotency tag is derived from exactly one repo’s commit. A two-input image needs a composite commit (<mono-sha>-<knowledge-sha>) fed into it, or a knowledge-only change produces no new tag and a naive nightly rebuild silently does nothing — see the cluster SOP’s check-image gotcha for the exact formula.
  • A prior attempt put this recipe in infra_k8s as a docs-image Pipeline plus a nightly CronJob (infra_k8s#174, closed). Inlining it in build.sh needs zero cluster-side changes and keeps the recipe next to the COPY .knowledge/ that is its only reason to exist. Nightly rebuilds were dropped — the Cloudflare Pages deploy already refreshes nightly.

Gotchas

  • Only .mdx is link-linted. bun run lint:docs covers .mdx only; bun run build does not catch broken internal links at all. Knowledge pages are plain .md (MDX would choke on the <placeholder>/{brace} syntax these notes are full of), so their links are never automatically checked — moving the product docs to /documentation/* broke 17 links that the build reported as green. Check a .md page’s links against dist/ by hand after any path-affecting change.
  • Every doc under wiki/ should have a real H1 (not just OKF frontmatter title) — Nimbus strips it for rendering, but the sync tooling and any local reading both benefit from an authored title rather than a slug-derived one.
Navigation

Type to search…

↑↓ navigate↵ selectEsc close