Skip to content

Working on the docs

This documentation site (docsite/) is a separate project from the Cargo workspace — its own build graph, its own gate, its own dependency stream. This page covers how it is organized and how to change it without breaking the gate. The governing contract is .claude/rules/docsite.md; the authoring mechanics live in the docsite, docsite-sync, and mermaid-diagrams skills.

docsite/ is Astro Starlight under bun. It has its own package.json, bun.lock, node_modules, and dist/. It is not a member of the Cargo workspace and not part of ui/control-plane’s bun project — it shares zero dependencies with either by design. Workspace CI does not build it; a path-filtered workflow does.

Two consequences follow from that isolation:

  • It consumes outputs, never source. The site may ingest artifacts of the other stacks — the workspace version from apomesh-bump -- current, a committed OpenAPI snapshot — but never their source trees as build inputs. Documentation about code is written by reading HEAD, not by importing it.
  • It is never a contract-parity surface. A wire or closed-enum change does not sweep the docsite. Doc updates for code changes ride the sync loop below, not the parity gate.
Terminal window
cd docsite && bun install && bun run build

A red build never lands. The gate catches broken sidebar slug: references (a moved or missing page fails the build), invalid frontmatter, Mermaid render errors, and the coverage check. It does not catch, so grep for these by hand after moving pages:

  • relative ../.. links that 404 — use root-relative /section/page/ links;
  • links that only resolve through a redirects entry — rewrite to canonical;
  • stale #anchor fragments after a heading rename.

astro.config.mjs is not hot-reloaded — restart bun run dev after sidebar edits.

Pages are classified by Diátaxis type crossed with audience:

SectionTypeAudience
getting-started/Tutorialany newcomer
concepts/Explanationanyone needing the “why”
operate/How-tooperators running the stack + console
build/How-toSDK consumers + integrators
contribute/How-to + explanationdevelopers building apomesh
reference/Referencelook-up, all roles (autogenerated)

Classify a page before writing it — the Diátaxis type decides its home. A few IA rules keep the sidebar coherent: group by audience or concern, never by crate (crate-shaped pages live only under reference/); no single-page groups; keep journey depth to at most three (Section → Group → page, only the collapsed reference/ trees go deeper); and one canonical home per concept — every other page links there rather than re-explaining.

Two tracked files keep the site honest against the moving codebase.

  • docsite/coverage.json is the semantic index: every workspace crate is classified documented, planned, or internal. A documented entry must name a page slug that exists; an internal entry gives a one-line reason; planned is the visible documentation backlog. scripts/check-coverage.mjs runs as part of the build and discovers crates by globbing the workspace, so a new crate cannot land silently undocumented — the author classifies it or the build goes red.
  • docsite/.sync-state.json anchors the last commit the docs were reconciled against (lastSyncedCommit) plus any pending work-list. The docsite-sync skill owns the loop: diff the range since the anchor, map changed paths to doc targets, update one target per iteration, and advance the anchor only after honest triage. A stale anchor is visible debt; an anchor advanced past unexamined commits is a defect.

Changes land on one of two rungs, per .claude/rules/docsite.md:

  • Content edits — pages, sidebar entries, coverage or sync-state flips — ride rung 1: commit direct to main, but only after the local build gate passes.
  • Tooling / config / component editspackage.json, the structure of astro.config.mjs, scripts/, src/components/, the CI workflow — ride rung 2: a lean gated PR.

docs/architecture.md and the rest of docs/ remain the canonical in-repo sources. The docsite derives from them and from the code, and never claims authority over either. Where the docsite and the code disagree, the docsite is the bug. Rule 4’s “directional docs don’t inventory state” binds docsite prose too: no typed version strings and no drift-prone counts — the version is injected at build time from the bump tool.

  • Deep authoring mechanics (sidebar levers, redirects, the Mermaid component, the coverage.json contract) live in the docsite skill.
  • Post-merge sync (“are the docs current?”) is the docsite-sync skill.