ADR-0032: Publish the docs with Docusaurus, built from the Markdown where it lives
Proposed
Status: proposed · 2026-11-04
Context
The documentation is about a dozen Markdown files spread over the repository: README.md, ARCHITECTURE.md, one README per package, the planning skills guide in .claude/skills/ with its vault-planning/conventions.md, and the ADRs in docs/adr/. They read well on GitHub one at a time, but there is no navigation across them, no search, and no stable URL to share for "how to set up the coach" or "why the judge never sees your notes".
Each file must stay readable on GitHub, links between files must work there, and nobody should have to keep a second copy in step. Obsidian callouts (> [!TIP]) and ASCII diagrams are part of how the files are written.
Decision
- The site is a Docusaurus app in
apps/docs, an Nx project nameddocs(tagtype:docs) withbuild,serve,serve-staticandlinttargets.apps/*joins the npm workspaces; the app's dependencies live in its ownpackage.json. - The Markdown files are the only source. One docs plugin instance is rooted at the repository and reads the files in place through an
includelist inapps/docs/src/sources.mjs. Nothing is copied or synced. Because every page is in one instance, Docusaurus resolves.mdlinks between them natively, so a link written for GitHub (../../README.md#set-it-up,docs/adr/0029-….md) works on the site unchanged. - The source files carry no site metadata. Slugs, sidebar labels and the ADR status classes are added at build time by
markdown.parseFrontMatterfrompageForinsources.mjs. The sidebar is Getting started, Architecture, Packages, Planning with Claude Code, Decisions; packages and ADRs are listed from the file system, so a new one appears without editing the site. - Three remark plugins adapt GitHub Markdown, and change no file: Obsidian callouts become admonitions; a relative link to a repository file that is not on the site (
LICENSE,coach.config.example.json,vault-planning/rules.md) becomes its GitHub URL; each ADR gets a status banner from its frontmatter, with links to the ADRs that supersede it or that it supersedes. The sidebar shows each ADR's status as a badge. - Files are parsed as CommonMark, not MDX (
markdown.format: 'detect'), so<,{and ASCII diagrams render as written. Code blocks never wrap and scroll sideways. - A broken link fails the build:
onBrokenLinks,onBrokenAnchorsandmarkdown.hooks.onBrokenMarkdownLinks(where Docusaurus 3.10 movedonBrokenMarkdownLinks) are allthrow. - Search is local (
@easyops-cn/docusaurus-search-local); no external service sees the docs or the queries. .github/workflows/docs.ymlbuilds the site on every pull request and push, and deploysmainto GitHub Pages athttps://push-based.github.io/ai-performance-coach/. Pages must be set to deploy from GitHub Actions in the repository settings.- kb-template's documentation stays in its own repository. Versioned docs wait for releases.
Consequences
- A README edit changes the site on the next build; there is no second copy to forget.
- Renaming or moving a documented file, or adding a new kind of page, means updating
INCLUDEandpageForinsources.mjs. - A link that works on GitHub but not on the site, or a heading anchor that no longer exists, now fails the build in pull requests.
- Obsidian callout types without a Docusaurus equivalent are mapped to the nearest admonition.
- The workspace carries Docusaurus and React as dependencies of
apps/docs, which the coach itself never imports.