feat(docs): vitepress site for docs/, mermaid rendering, ci build workflow #154
Reference in New Issue
Block a user
Delete Branch "feat/docs-site-vitepress"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implementation of ADR-0022. Stands up the static documentation site that renders
docs/**/*.md(architecture diagrams, daily-dev guide, ADRs, onboarding) via VitePress +vitepress-plugin-mermaid, behind a Gitea Actions build gate.Local dev:
pnpm docs:dev. Full build:pnpm docs:build(~9 s, output indocs/.vitepress/dist/).What lands
Dependencies
vitepress 1.6.4,vitepress-plugin-mermaid 2.0.17,mermaid 11.15.0— workspace devDependencies. No runtime impact onportal-shell/portal-admin/portal-bff.docs/.vitepress/config.mtsThe single source of truth for the site. Highlights:
srcExcludedropsdocs/README.md(git/IDE-only index per ADR-0022's option A) anddocs/decisions/template.md(authoring scaffold).rewritesmapsdecisions/README.md→decisions/index.mdso/decisions/resolves to the curated tag-grouped landing while the source filename stays git-conventional.ignoreDeadLinksskips:localhost:*URLs (Jaeger, OTLP — only resolve in a live dev session),../CLAUDE,../../apps/**,../../infra/**,../../notes/**) — intentional from git/IDE consumers; not the site's job to render them,./template,./README) — file exists in the repo, just not in the site./decisions/—adrSidebarItems()walksdocs/decisions/00*-*.mdand emits sortedADR-NNNN — titleentries. Adding an ADR is a single-file change, noconfig.mtsedit.withMermaid()withsecurityLevel: 'strict'so diagrams can't inject arbitrary HTML.docs/index.mdVitePress Hero landing with four feature cards (Architecture, Decisions, Development, Onboarding).
docs/development.md— two surgical fixes[setup/](setup/)→[setup/01-wsl-terminal-setup.md](setup/01-wsl-terminal-setup.md). Folder-style links don't resolve cleanly undercleanUrls: true; pointing at the first onboarding page is both correct and useful.${{ github.* }}in<code v-pre>…</code>. VitePress runs every Markdown file through the Vue template compiler, which sees the inline{{ … }}as an interpolation.v-prekeeps the literal text intact. The rest of the source is unaffected.package.jsonThree new scripts:
Pure pnpm scripts, no Nx project — the site has no cross-project dependency graph to track.
.gitea/workflows/docs-site.ymlTriggers on push to
mainand on PR, scoped bypaths:todocs/**,package.json,pnpm-lock.yaml, and the workflow itself. Three steps:pnpm install --frozen-lockfilepnpm docs:buildgrepADR-0009's rendered HTML forclass="mermaid"or<svg>so a silent Mermaid-plugin breakage on a major upgrade fails the workflow rather than ship a site with raw code blocks where diagrams should be.docs/.vitepress/dist/as adocs-siteartifact (30-day retention). The actual rsync to the static host lands when the future infrastructure ADR locks the deployment target..gitignoreExcludes
docs/.vitepress/{cache,dist}/so local builds don't leak into commits.Notes for the reviewer
config.mtsand notconfig.ts? VitePress is ESM-only, andvitepress-plugin-mermaidfollows. Vite loads.tsconfig files via its CJS bundler in this workspace's setup and chokes on the ESM imports..mtsflips the loader to ESM and the build succeeds. Same pattern is used elsewhere in the workspace (jest.config.cts, appvite.config.mts).docs/project.json)? The doc site has no Nx-trackable dependencies (it consumes.mdfiles, not TypeScript projects). Putting it in the Nx graph adds ceremony with no caching benefit — VitePress's incremental rebuilds are sub-second already, and the site never has cross-projectaffectedsemantics. Pure pnpm scripts keep the surface small.```mermaidblocks rendered as raw code without anyone noticing — until an RSSI clicks ADR-0009 and sees no diagram. Cheap grep gate, real signal.docs.portal.apf.fror a sub-path) is provisional. Locking an rsync target now would couple this PR to a not-yet-made infra decision. Artifact upload is the staging mechanism — manual drop on the host until the infrastructure ADR formalises the target.ignoreDeadLinksrather than fixing every cross-repo reference? The cross-repo links are genuinely useful from a git/IDE perspective (where the docs/ markdown is browsed alongside the rest of the codebase). Rewriting them tohttps://git.unespace.com/julien/apf_portal/src/branch/main/…would make them work on the site but lose the IDE quick-jump. Skipping at site-build time is the right trade-off — the site reader gets a graceful "link doesn't exist here" if they click, the IDE reader gets a working jump.Test plan
pnpm docs:buildsucceeds in ~9 s. Output atdocs/.vitepress/dist/contains anindex.html, every ADR, the development guide, the architecture diagrams, and the three setup pages.grep 'class="mermaid"' docs/.vitepress/dist/decisions/0009-…htmlreturns a match.pnpm exec nx run-many -t format:check lint test buildfor the 6 main projects — 18/18 tasks green, no Nx regression from the new top-level config.pnpm docs:dev, openhttp://localhost:5173, walk through:/decisions/0009-…renders the OIDC sequence diagram (Mermaid SVG, not raw text)./decisions/0010-…ERD or/architectureC4 diagrams likewise./decisions/./decisions/lists ADRs by tag (no regression on the source markdown).What's next
Once the deployment target is fixed (future infra ADR), wire the rsync step into the workflow — that lands as a small follow-up PR. Until then the artifact carries the bundle.
Implementation of ADR-0022. * `vitepress`, `vitepress-plugin-mermaid` and `mermaid` added to workspace devDependencies. Build settled at ~9 s for the full site, sub-second incremental in dev. * `docs/.vitepress/config.mts`: * `srcExclude` drops `docs/README.md` (git/IDE-only index) and `docs/decisions/template.md` (authoring scaffold). * `rewrites` maps `decisions/README.md` → `decisions/index.md` so `/decisions/` resolves to the curated landing while the source stays git-friendly. * `ignoreDeadLinks` skips cross-repo refs (`../CLAUDE`, `../../apps/**`, `../../notes/**`), `localhost:*` dev URLs, and the deliberately-excluded `README`/`template` references — the source stays usable from a git/IDE reader without breaking the site build. * Auto-generated sub-sidebar for `/decisions` walks `00NN-*.md` so adding an ADR is one file. * Mermaid via `withMermaid` with `securityLevel: 'strict'`. * `docs/index.md` — VitePress Hero landing with four feature cards (Architecture, Decisions, Development, Onboarding). * `package.json` exposes `docs:dev`, `docs:build`, `docs:preview`. * `docs/development.md` (line ~5): `[setup/](setup/)` → first page, since folder-style links don't resolve cleanly under `cleanUrls`. Line 330: wrap `${{ github.* }}` in `<code v-pre>…</code>` so VitePress's Vue template parser doesn't trip on the curly-brace interpolation. * `.gitea/workflows/docs-site.yml` — builds on every PR (gate on parse errors + genuine dead links), uploads the dist as an artifact on push to main. The Mermaid plugin regression fence greps for `class="mermaid"` / `<svg>` in ADR-0009's rendered HTML. * `.gitignore` excludes `docs/.vitepress/{cache,dist}/`. Deployment target stays provisional per ADR-0022; the workflow publishes a `docs-site` artifact for now. The rsync step lands once the future infrastructure ADR locks the host.