Docs diagrams — Mermaid SSOT, diagram-design SVGs
Headline diagrams on the docs site are hand-crafted SVGs in the
diagram-design editorial
system, generated from Mermaid sources. The split:
docs/diagrams/*.mmd — the source of truth. Diffable, reviewed in PRs,
outside docs_dir so MkDocs never publishes it.
docs/diagrams/manifest.yml — the mapping: each source, its SVG pair,
the pages embedding it, and the source's sha256 at generation time.
python3 docs/diagrams/verify.py checks it (CI runs it in the
Documentation (strict) job, so a drifted .mmd fails the PR);
--update refreshes the hash after a regeneration.
docs/manual/assets/diagrams/<name>-light.svg + <name>-dark.svg —
generated build products. Never hand-edit beyond regeneration.
- The embedding page inlines both via
pymdownx.snippets inside
dd-diagram dd-light / dd-dark divs; assets/extra.css switches them on
Material's data-md-color-scheme and loads the fonts (inline SVG inherits
page fonts — <img> embedding would silently lose them).
Scope: headline diagrams only — currently concepts/lifecycle.md's
flowchart. Workaday diagrams (sequence diagrams, guides) stay plain
```mermaid blocks. A diagram earns the treatment when it carries a
page's thesis, not because it exists.
The rule
Any PR that changes a docs/diagrams/*.mmd regenerates its SVG pair in the
same PR — the docs-in-same-PR rule applied to diagrams. Conversely, never
change a generated SVG's content without changing its .mmd first.
Regenerating
- Get the upstream skill:
/plugin marketplace add cathrynlavery/diagram-design
and install diagram-design@diagram-design (or clone the repo and read
skills/diagram-design/SKILL.md). Version pinned by this workflow: 2.5.
- Follow its import-mermaid flow against the changed
.mmd
(scripts/mermaid_extract.py, then redraw — never mimic Mermaid's layout).
Dials: format svg (as the inline pair below), size doc-wide, detail
balanced, audience mixed.
- Apply the Skills Gateway skin (below), not the shipped default.
- Produce both variants with variant-scoped CSS class prefixes
(
ddl- light, ddd- dark) and variant-suffixed marker/title/desc ids
— both SVGs are inlined into one HTML document, so anything global collides.
Each SVG paints its own paper <rect> and carries role="img" +
aria-labelledby per the upstream accessible-SVG contract.
- Verify: upstream
scripts/self_check.py and verify-geometry.py must both
pass; then mkdocs build --strict.
- Refresh the manifest:
python3 docs/diagrams/verify.py --update, then a
plain verify.py run must print OK.
- Report the fidelity ledger (merges/collapses/drops vs the
.mmd) in the PR.
Skills Gateway skin
Mapped from the portal's design system (--primary
oklch(0.541 0.247 293.01)); the docs Material palette is deep purple, so the
accent matches both.
| Role |
Light |
Dark |
| paper |
#f7f5fa |
#201c2a |
| node-fill |
#ffffff |
#2c2739 |
| ink |
#26222f |
#f1eef8 |
| muted |
#5c576e |
#b3acc6 |
| soft |
#837d94 |
#8d86a1 |
| rule |
rgba(38,34,47,0.12) |
rgba(241,238,248,0.12) |
| rule-solid |
#c9c4d6 |
rgba(241,238,248,0.24) |
| accent |
#7c3aed |
#a78bfa |
| accent-tint |
rgba(124,58,237,0.08) |
rgba(167,139,250,0.10) |
| accent-soft (security/boundary) |
rgba(124,58,237,0.5) |
rgba(167,139,250,0.5) |
| zone-fill |
ink @ 0.02 |
ink @ 0.02 |
| store-fill |
ink @ 0.05 |
ink @ 0.06 |
| ext-fill / ext-stroke |
ink @ 0.03 / 0.30 |
ink @ 0.03 / 0.30 |
Typography per upstream: Geist (names), Geist Mono (technical/sublabels/
labels), Instrument Serif italic (annotations only). Fonts load site-wide from
assets/extra.css.
House conventions on top of the upstream system:
- Accent budget spends on trust: the focal treatment goes to the publish
gate / trust-boundary crossing, and the security-dashed zone marks
quarantine. Never spend it on decoration.
- The append-only ledger renders as a full-width store bar with one
annotation instead of per-node dotted edges.
Adding a new headline diagram
Add docs/diagrams/<name>.mmd, generate the pair, add the entry to
docs/diagrams/manifest.yml (verify.py --update fills the hash), and embed
with:
<!-- Diagram source of truth: docs/diagrams/<name>.mmd (Mermaid). -->
<div class="dd-diagram dd-light">
--8<-- "docs/manual/assets/diagrams/<name>-light.svg"
</div>
<div class="dd-diagram dd-dark">
--8<-- "docs/manual/assets/diagrams/<name>-dark.svg"
</div>
Snippet paths resolve from the repo root (mkdocs runs there).
1---2name: docs-diagrams3description: Regenerate the docs site's editorial SVG diagrams from their Mermaid sources in docs/diagrams/ using the diagram-design system with the Skills Gateway skin. Load whenever a .mmd source changes, a new headline diagram is added, or a docs PR touches a page that embeds a dd-diagram SVG pair.4---56# Docs diagrams — Mermaid SSOT, diagram-design SVGs78Headline diagrams on the docs site are hand-crafted SVGs in the9[diagram-design](https://github.com/cathrynlavery/diagram-design) editorial10system, generated from Mermaid sources. The split:1112- **`docs/diagrams/*.mmd`** — the source of truth. Diffable, reviewed in PRs,13 outside `docs_dir` so MkDocs never publishes it.14- **`docs/diagrams/manifest.yml`** — the mapping: each source, its SVG pair,15 the pages embedding it, and the source's sha256 at generation time.16 `python3 docs/diagrams/verify.py` checks it (CI runs it in the17 `Documentation (strict)` job, so a drifted `.mmd` fails the PR);18 `--update` refreshes the hash after a regeneration.19- **`docs/manual/assets/diagrams/<name>-light.svg` + `<name>-dark.svg`** —20 generated build products. Never hand-edit beyond regeneration.21- The embedding page inlines both via `pymdownx.snippets` inside22 `dd-diagram dd-light` / `dd-dark` divs; `assets/extra.css` switches them on23 Material's `data-md-color-scheme` and loads the fonts (inline SVG inherits24 page fonts — `<img>` embedding would silently lose them).2526**Scope: headline diagrams only** — currently `concepts/lifecycle.md`'s27flowchart. Workaday diagrams (sequence diagrams, guides) stay plain28```` ```mermaid ```` blocks. A diagram earns the treatment when it carries a29page's thesis, not because it exists.3031## The rule3233**Any PR that changes a `docs/diagrams/*.mmd` regenerates its SVG pair in the34same PR** — the docs-in-same-PR rule applied to diagrams. Conversely, never35change a generated SVG's content without changing its `.mmd` first.3637## Regenerating38391. Get the upstream skill: `/plugin marketplace add cathrynlavery/diagram-design`40 and install `diagram-design@diagram-design` (or clone the repo and read41 `skills/diagram-design/SKILL.md`). Version pinned by this workflow: 2.5.422. Follow its **import-mermaid** flow against the changed `.mmd`43 (`scripts/mermaid_extract.py`, then redraw — never mimic Mermaid's layout).44 Dials: format `svg` (as the inline pair below), size `doc-wide`, detail45 `balanced`, audience `mixed`.463. Apply the **Skills Gateway skin** (below), not the shipped default.474. Produce both variants with **variant-scoped CSS class prefixes**48 (`ddl-` light, `ddd-` dark) and variant-suffixed marker/`title`/`desc` ids49 — both SVGs are inlined into one HTML document, so anything global collides.50 Each SVG paints its own paper `<rect>` and carries `role="img"` +51 `aria-labelledby` per the upstream accessible-SVG contract.525. Verify: upstream `scripts/self_check.py` and `verify-geometry.py` must both53 pass; then `mkdocs build --strict`.546. Refresh the manifest: `python3 docs/diagrams/verify.py --update`, then a55 plain `verify.py` run must print OK.567. Report the fidelity ledger (merges/collapses/drops vs the `.mmd`) in the PR.5758## Skills Gateway skin5960Mapped from the portal's design system (`--primary`61`oklch(0.541 0.247 293.01)`); the docs Material palette is deep purple, so the62accent matches both.6364| Role | Light | Dark |65| --- | --- | --- |66| paper | `#f7f5fa` | `#201c2a` |67| node-fill | `#ffffff` | `#2c2739` |68| ink | `#26222f` | `#f1eef8` |69| muted | `#5c576e` | `#b3acc6` |70| soft | `#837d94` | `#8d86a1` |71| rule | `rgba(38,34,47,0.12)` | `rgba(241,238,248,0.12)` |72| rule-solid | `#c9c4d6` | `rgba(241,238,248,0.24)` |73| accent | `#7c3aed` | `#a78bfa` |74| accent-tint | `rgba(124,58,237,0.08)` | `rgba(167,139,250,0.10)` |75| accent-soft (security/boundary) | `rgba(124,58,237,0.5)` | `rgba(167,139,250,0.5)` |76| zone-fill | ink @ 0.02 | ink @ 0.02 |77| store-fill | ink @ 0.05 | ink @ 0.06 |78| ext-fill / ext-stroke | ink @ 0.03 / 0.30 | ink @ 0.03 / 0.30 |7980Typography per upstream: Geist (names), Geist Mono (technical/sublabels/81labels), Instrument Serif italic (annotations only). Fonts load site-wide from82`assets/extra.css`.8384House conventions on top of the upstream system:8586- **Accent budget spends on trust**: the focal treatment goes to the publish87 gate / trust-boundary crossing, and the security-dashed zone marks88 quarantine. Never spend it on decoration.89- The append-only ledger renders as a full-width store bar with one90 annotation instead of per-node dotted edges.9192## Adding a new headline diagram9394Add `docs/diagrams/<name>.mmd`, generate the pair, add the entry to95`docs/diagrams/manifest.yml` (verify.py `--update` fills the hash), and embed96with:9798```html99<!-- Diagram source of truth: docs/diagrams/<name>.mmd (Mermaid). -->100<div class="dd-diagram dd-light">101--8<-- "docs/manual/assets/diagrams/<name>-light.svg"102</div>103<div class="dd-diagram dd-dark">104--8<-- "docs/manual/assets/diagrams/<name>-dark.svg"105</div>106```107108Snippet paths resolve from the repo root (mkdocs runs there).