Skip to content

0003. VitePress as the docs shell around the Archify diagram pipeline

  • Status: Accepted
  • Date: 2026-09-10
  • Deciders: Konrad engagement team
  • Needs client validation: No — internal working tooling. It becomes client-facing only if open question 1 resolves toward a hosted handoff, which is a separate decision.
  • Domain: tooling

Context

ADR-0001 chose Archify for diagrams. Archify is a one-diagram-in, one-standalone-HTML-document-out renderer: each artifact is ~800 KB with the entire viewer, CSS, JS and fonts inlined. It has no notion of an index, sidebar, navigation, or site, and no batch or fragment mode.

Everything navigational was therefore bespoke — renderIndex() hand-wrote the gallery as a template literal, renderTimeline() hand-wrote the version pages, and scripts/dev.mjs was a hand-rolled HTTP + SSE server. That was proportionate for one diagram. It does not carry a sidebar, an open-questions section, and the twelve target-state architecture pages named in ../architecture/README.md.

Two constraints narrowed the field:

  • The acceptable handoff format is unresolved (open question 1). Content must stay portable — pandoc docs/**/*.md has to keep working, so a framework whose selling point is non-standard markdown syntax is a liability, not a feature.
  • .claude/skills/archify/ is a pinned upstream copy that must not be edited. Diagrams can only be integrated by URL contract.

A finding during evaluation changed the options materially: Archify has an undocumented embed mode. ?embed=1 (99 data-embed rules in assets/template.html, intent stated in the source comment) strips the toolbar, header, cards, legend and every keyboard-bound panel, leaving the diagram surface. Combined with #view=<id>&beat=<node>, a prose page can embed a diagram deep-linked to a guided chapter with no keyboard conflict and no edit to the pinned skill.

Decision

Adopt VitePress as the host application. docs/ becomes its srcDir — files stay exactly where they are, so relative links, GitHub folder browsing and pandoc all keep working.

The diagram pipeline stays ours and stays separate. scripts/lib/manifest.mjs writes diagrams/manifest.json as the single seam; the site reads it and nothing else. Archify output moves to docs/public/artifacts/, which Vite copies verbatim — so the injected dock survives byte for byte.

Diagrams are linked, not embedded, on their own routes: the viewer binds / R L P F E ? on the document, wants the full viewport, and its export menu degrades in a frame. Inline previews inside prose use a single <Diagram> component, which switches the viewer to ?embed=1.

Alternatives considered

OptionProsConsWhy not
Astro + StarlightBest-in-class accessible sidebar; Pagefind search; Zod-validated frontmatter~400 transitive packages; MDX-flavoured markdown (:::note, <Card>) is content lock-in; requires frontmatter title on every fileThe MDX lock-in points the wrong way while the handoff format is undecided. It would also retire only ~270 of 1,259 bespoke lines — all 403 lines of version/delta machinery stay regardless — so the maintenance surface goes up, not down
Next.jsFamiliar; large ecosystemReact SSR framework for ~30 static markdown files; the docs layer (sidebar, TOC, prev/next) would still be hand-built; adds React to a repo with no .tsxStrictly dominated. Nothing here is dynamic
DocusaurusMature docs platformHeaviest option; React; MDX-firstSame lock-in as Starlight, with more weight
Extend scripts/ with a vendored markdown parserKeeps the repo at zero dependencies and no lockfile — a real asset for an InfoSec review; total control~635 new lines owned for the life of the repo; a hand-rolled sidebar will be less accessible than a maintained one; no search or link checking without more codeThe closest call. Rejected because an accessible, responsive, keyboard-navigable sidebar is the one item on the list that is genuinely hard to hand-roll well, and it is precisely what was asked for
Do nothingZero costNo sidebar, no doc pages, no home for open questions; twelve architecture docs would land as a flat folderDoes not meet the need

VitePress wins the narrow question against Starlight on markdown portability: its markdown stays close to CommonMark, so the pandoc → Word/Confluence/PDF path stays open.

Consequences

Easier. Sidebar navigation, prev/next, table of contents, responsive and keyboard-accessible layout, and dark mode arrive maintained rather than hand-written. Writing a new architecture doc is now creating one markdown file. ~350 lines of HTML-in-template-literals were deleted (renderIndex, renderTimeline, scripts/serve.mjs, scripts/lib/static.mjs, and the server half of scripts/dev.mjs). Diagram status is machine-readable, so the "placeholder — not for client viewing" warning finally appears in the browser instead of only in markdown.

Harder. npm install is now required; the repo's "clone and run, zero dependencies" property is gone. That was a genuinely good answer for a handoff to Manulife engineers and no longer applies — 125 packages, all dev-only, producing static output. npm audit currently reports advisories in the Vite/esbuild dev server (path traversal, dev-server request handling); the published output is static HTML and the dev server binds 127.0.0.1, so the exposure is a developer machine, not the client. Worth re-checking before any hosted deployment.

A new failure mode exists: the site can render cleanly while a diagram is stale. The manifest carries ok, error, stale and builtAt for exactly this, and the affected pages show a banner — but the terminal remains authoritative.

Cost implications. None for WS 3 pricing: this is internal authoring tooling, not a client deliverable, and adds no licence cost. If open question 1 resolves toward a hosted handoff, the deployment and access-control work is a separate, small line item.

Dependencies and open questions

  • Open question 1 (handoff format) is the one that could reverse part of this. If the answer is "Word/PDF only", the markdown is unaffected and VitePress simply goes unused for handoff — which is why content stays CommonMark and no MDX syntax is permitted beyond <Diagram>.
  • Deployment is deliberately not wired. If this is ever published, it needs access control in front of it first: Manulife target-state architecture must not sit on a public URL.
  • Adding or removing a diagram requires a dev-server restart, because the sidebar reads the manifest once at startup. Editing an existing diagram hot-reloads normally.

Internal working knowledge base — not for external distribution.