Appendix H: Architecture-as-Code Reference
Overview
Architecture-as-Code is an S4U methodology principle: documentation is machine-readable infrastructure consumed by both humans and AI agents. A feature doesn't exist until its architecture page exists. Documentation drift is structurally impossible because the page is created before the code.
This appendix provides the complete reference for implementing Architecture-as-Code in any project using Docusaurus.
Frontmatter Schema
Every architecture page uses structured YAML frontmatter:
---
title: Component Name
sidebar_position: 12
description: One-line description for search and AI context
components:
- app/services/example_service.py
- app/models/example.py
tests:
- tests/test_example_service.py
data_flow:
- input -> processing -> output
depends_on:
- architecture/other-component
owners:
- app/agents/orchestrator.py
last_verified: 2026-03-29
status: implemented
---
Field Definitions
| Field | Type | Required | Purpose |
|---|---|---|---|
components | list[str] | Yes (for code pages) | Source files this page documents. Relative to repo root. |
tests | list[str] | Recommended | Test files that verify these components. Used by Stop hook. |
data_flow | list[str] | Optional | Arrow-notation data flows. Describes how data moves. |
depends_on | list[str] | Optional | Other doc pages this component depends on (relative paths, no extension). |
owners | list[str] | Optional | Files that consume/orchestrate this component. |
last_verified | date | Yes | Last date someone confirmed page matches code. |
status | enum | Yes | implemented, in-progress, or planned. |
Status Values
| Status | Meaning | AI Agent Behavior |
|---|---|---|
implemented | Working code exists | Trust as architectural truth |
in-progress | Actively being built | Check for partial implementation |
planned | Vision, no code yet | Understand direction, don't search for code |
Rules
- One page per architectural boundary — not per feature, not per tutorial.
componentsMUST use relative paths from repo root.- A file MAY appear in multiple pages'
componentslists. status: plannedpages MUST NOT listcomponentsthat don't exist.- Pages without backend components (overviews, frontend, methodology) get only
last_verifiedandstatus.
Architecture Index
A build plugin scans all pages with structured frontmatter and generates an index JSON file:
{
"component_map": {
"app/services/example.py": ["architecture/example-page"]
},
"data_flows": {},
"dependency_graph": {},
"status_summary": { "implemented": 30, "planned": 5 },
"coverage": {
"total_backend_files": 100,
"documented_files": 40,
"coverage_pct": 40.0
},
"stale_pages": [],
"generated_at": "2026-03-29T12:00:00Z"
}
Implementation
For Docusaurus projects, implement as a postBuild lifecycle plugin:
- Scan all
.md/.mdxfiles underdocs/ - Parse YAML frontmatter for architecture metadata
- Build component map, data flows, dependency graph
- Calculate coverage by scanning backend source directories
- Identify stale pages (last_verified > 30 days)
- Write index to project root as
docs/architecture-index.json
The index is a development artifact (committed to repo), not a build output (not deployed).
CLAUDE.md / AGENTS.md Integration
Add this protocol to the project's instruction file:
### Architecture Documentation Protocol
Before modifying any backend file under `app/`:
1. Read `docs/architecture-index.json`
2. Look up the file in `component_map`
3. If found, read the listed Docusaurus page(s)
4. After implementation, verify documentation is still accurate
After completing changes:
- If doc is stale (>30 days), update and set `last_verified` to today
- If new file has no doc page, add it to the nearest page's `components:`
ADR Publishing (canonical → site)
The architecture index reads frontmatter the page authors already wrote. ADRs are
the mirror case: the canon lives in docs/adr/ADR-NNNN-<slug>.md (the format and
register integrity are owned by appendix-g), and the living-doc site wants those
same decisions rendered as pages. Hand-copying them drifts — the published mirror
silently lags the canon. A real instance: a site's ADR section stopped at ADR-0049
while the canon had reached 0066, because each new ADR needed a manual copy plus a
sidebar edit and the step was forgotten.
The fix is a generator, not a copy step — and it is the natural generator for the §7.5 freshness gate to pin:
# build/start prestep — regenerate the published mirror from canon
templates/scripts/generate-adr-mirror.sh <docusaurus>/docs/adr
# §7.5 gate — fail the build if the committed mirror lags canon
templates/scripts/check-generated-fresh.sh \
--generator templates/scripts/generate-adr-mirror.sh \
--out <docusaurus>/docs/adr
Implementation
templates/scripts/generate-adr-mirror.sh (output dir as $1, source ADR_SRC,
default ./docs/adr):
- Glob canonical
ADR-NNNN-<slug>.mdin C-locale (deterministic) order. - For each, derive
id=NNNN-<slug>(lowercased),sidebar_position= the ADR number + 1, andtitlefrom the first# ADR-NNNN: <title>heading. - Write
<out>/NNNN-<slug>.md= Docusaurus frontmatter + the canonical body verbatim (the body is the single source of truth; the page is never edited by hand).
Two properties make it a clean §7.5 generator:
- Deterministic. Glob order is the C-locale sort, the title is read from the file, the YAML scalar is quote-escaped, and nothing stamps a timestamp or random value — so a fresh run over an unchanged canon is byte-identical to the committed mirror. (Determinism is the one precondition for the regenerate-and-diff gate.)
- Owns only its files. It rewrites the
NNNN-*.mdADR pages and nothing else, so an authoredindex.mdor_category_.jsonin the same directory survives and cancels out of the diff.
Sidebar
Make the ADR sidebar autogenerated ({type: 'autogenerated', dirName: 'adr'})
so a freshly generated page joins the nav with no manual edit — ordered by the
sidebar_position the generator stamps. The two together (generate prestep +
autogenerated sidebar) close both halves of the drift: missing pages and missing
nav entries.
Single source of truth vs. legacy curation
The generator is full-generate: every published ADR page is reproduced from canon, so canon is authoritative and the gate is meaningful. A project that already has hand-curated published ADR pages whose bodies have diverged from canon must reconcile first — either fold the curation back into the canonical files (then full-generate), or scope the generator/gate to only the ADR numbers it owns. Do not run a full-generate gate over divergent curated pages; it will (correctly) report them stale. Per appendix-g an accepted ADR body is immutable, so once reconciled the bodies stay in sync by construction.
Tier: Recommended (§14) — adopted where a project publishes its ADRs to a living-doc site; the generator is generic (canon dir in, Docusaurus dir out) and carries no project specifics.
Sync Surfacing
A script checks documentation freshness for modified files (advisory — it warns, it does not block).
Staleness Check (Advisory)
For each modified .py file in a commit:
- Look up in
architecture-index.jsoncomponent_map - Read corresponding doc page's
last_verified - If older than 30 days → warn with an actionable message (
templates/hooks/check-doc-staleness.shexits 0; it surfaces stale docs at review, it never blocks the commit)
Coverage Check (Warning)
New .py files without a component_map entry → warn (not block).
The --docs-verified Flag
Updates last_verified on all relevant doc pages without requiring content changes — for when you reviewed and confirmed accuracy.
Documentation-First Development
The brainstorming skill creates a Docusaurus placeholder page BEFORE code exists:
Brainstorm → Spec + Doc placeholder (status: planned)
→ Plan → Implement → Update page (status: implemented) + set last_verified
This means:
- The architecture index knows about the feature before code exists
- AI agents see
status: plannedand understand the direction - The implementation plan includes "update doc to implemented" as final task
- Documentation drift is structurally impossible for new features
Test Mapping
The tests: frontmatter field maps components to their test files:
components:
- app/services/example_service.py
tests:
- tests/test_example_service.py
- tests/test_example_integration.py
The Stop verification hook uses this mapping: "For each modified file, did you run ALL mapped tests?"
Rollout Guide
Phase 1 (day 1): Add frontmatter to 10 most critical pages. Build index plugin. Add CLAUDE.md protocol.
Phase 2 (week 1): Add frontmatter to all remaining pages. Enable the advisory sync check.
Phase 3 (ongoing): Integrate with brainstorming/planning skills. Track coverage. Target 80%+.
Evidence
In one line: the pattern has been run in production — structured frontmatter across dozens of architecture pages, an auto-generated component index, and an advisory sync check (warns on stale docs, never blocks), brought up from a low initial coverage figure and tracked upward over time. Treat coverage as a ratchet, not a launch gate.
Canonical site template
A project's living-doc site should not reinvent the presentation layer. The
canonical, proven config lives at templates/docusaurus-site/ — scaffold
from it rather than from a bare create-docusaurus.
It provides, as defaults to keep: @docusaurus/theme-mermaid with the navy
themeVariables palette and the pinned sequenceDiagram contrast fix; a
documented semantic classDef palette (node roles, not raw hexes); a
collapsible left sidebar (hideable + autoCollapseCategories); a
collapsible TOC (native mobile + a swizzled desktop component that degrades
safely); and onBrokenLinks: 'throw' — which doubles as the Core link-integrity
blocking mechanism for tiered doc-sync (§7.5).
Accessibility (normative): every diagram and the site palette MUST meet
WCAG AA (4.5:1) text contrast in both light and dark mode (the
appendix-b standard, applied to diagrams). The semantic classDef palette is
chosen to satisfy this; a new node role is verified against AA in both modes
before use.
Tier: Recommended (§14) — the living-doc site itself is project-specific, so
the template is adopted where a site is warranted, not cargo-culted everywhere.
Full design rationale: specs/2026-06-14-docusaurus-site-template-design.md.