Skip to content

Commit d166345

Browse files
docs: split Mermaid style guide out of AGENTS.md under size gate (#180)
AGENTS.md was 16867 bytes, over the 12288-byte file-size gate that scans the whole tree, so every PR failed the gate. Move the detailed diagram authoring rules into two published, cross-linked convention pages and leave AGENTS.md pointing to them. - conventions/mermaid-style: theme directive, shape vocabulary, classDef and linkStyle palettes, the four narrative shapes, density caps. - conventions/mermaid-links: node navigation via the click directive and the external-URL workaround. diagramming.mdx now points at the two pages instead of AGENTS.md; both pages are added to the Documentation standards nav. No information lost; AGENTS.md is now 4378 bytes and no tracked .md/.nix/.tf exceeds 12288. Assisted-by: Claude:claude-opus-4-8[1m] Claude-Session: https://claude.ai/code/session_01Af17qRP9UiqtTzKzzFyDaM
1 parent cff3b86 commit d166345

5 files changed

Lines changed: 351 additions & 315 deletions

File tree

AGENTS.md

Lines changed: 12 additions & 313 deletions
Original file line numberDiff line numberDiff line change
@@ -75,322 +75,21 @@ plugin's `writing-clearly-and-concisely` skill before writing prose.
7575

7676
If a repo's GitHub visibility is `PRIVATE`, it does not appear here. Verify with `gh repo view OWNER/REPO --json visibility` when in doubt.
7777

78-
## Diagram style
78+
## Diagrams
7979

80-
Inline ` ```mermaid ` fenced blocks render natively in Mintlify with ELK layout.
81-
One diagram per concern — do not combine.
80+
Every repo with non-trivial architecture ships diagrams, rendered as inline
81+
Mermaid. The reader-facing summary — format, placement, what to draw, and when
82+
to reach for a table or `<Steps>` instead — is the published page
83+
[`conventions/diagramming`](conventions/diagramming.mdx).
8284

83-
### The canonical theme directive (use **exactly this**, byte-for-byte)
85+
The full authoring rules are split across two canonical pages. Follow both when
86+
you emit any Mermaid on this site:
8487

85-
Every Mermaid block on the site MUST begin with this directive. The
86-
`look:'handDrawn'` is non-negotiable — it gives the diagrams personality
87-
that matches the site's voice. Any deviation (different fontSize, missing
88-
`look`, different palette) is a bug.
89-
90-
```text
91-
%%{init: {'theme':'base','look':'handDrawn','themeVariables':{'fontFamily':'Geist','fontSize':'14px','primaryColor':'#102937','primaryTextColor':'#F4EFE6','primaryBorderColor':'#4FB3A9','lineColor':'#4FB3A9','secondaryColor':'#0B1D2A','tertiaryColor':'#1A2A38','clusterBkg':'rgba(79,179,169,0.08)','clusterBorder':'#4FB3A9'}}}%%
92-
```
93-
94-
To check the site is consistent:
95-
96-
```bash
97-
grep -h '%%{init:' --include='*.mdx' -r . | sort -u | wc -l
98-
# Must return 1.
99-
```
100-
101-
### Shape vocabulary
102-
103-
- Stadium `([Label])` for services and processes
104-
- Cylinder `[(Label)]` for data stores
105-
- Diamond `{Label}` for decisions / gates
106-
- Circle `((Label))` for endpoints / external actors
107-
- Hexagon `{{Label}}` for special-purpose nodes (use sparingly)
108-
- Subgraphs for things that physically or logically co-locate
109-
(a cluster, a host, a network, a repo group) — **never** for roles or phases
110-
111-
### Canonical classDef palette
112-
113-
Use the semantic class names below. Pick ONE per node based on what it
114-
represents; don't invent new classes per page. This keeps the same colour
115-
meaning the same idea everywhere.
116-
117-
```text
118-
classDef src fill:#102937,stroke:#E06B4A,stroke-width:2px,color:#F4EFE6;
119-
classDef hop fill:#102937,stroke:#4FB3A9,stroke-width:2px,color:#F4EFE6;
120-
classDef sink fill:#102937,stroke:#F4EFE6,stroke-width:2px,color:#F4EFE6;
121-
classDef gate fill:#102937,stroke:#E06B4A,stroke-width:2.5px,color:#F4EFE6;
122-
classDef external fill:#102937,stroke:#E6B35A,stroke-width:2px,color:#F4EFE6;
123-
classDef host fill:#102937,stroke:#4FB3A9,stroke-width:2px,color:#F4EFE6;
124-
classDef ai fill:#102937,stroke:#E06B4A,stroke-width:2px,color:#F4EFE6;
125-
classDef auto fill:#102937,stroke:#F4EFE6,stroke-width:1.5px,color:#F4EFE6;
126-
```
127-
128-
All classes share the same dark fill (`#102937`) so the diagram blends
129-
with the page; the **border colour** is what carries the semantic
130-
meaning. Text is always paper (`#F4EFE6`) — readable against the dark fill.
131-
132-
| Class | Border | Meaning |
133-
| --- | --- | --- |
134-
| `src` / `ai` / `gate` | Coral `#E06B4A` | Origin, AI-touched, or a decision gate. |
135-
| `hop` / `host` | Bright green `#4FB3A9` | Intermediate hops, the parent shell, hosts. |
136-
| `sink` / `auto` | Paper `#F4EFE6` | Sinks (Splunk indexer), automation steps. |
137-
| `external` | Amber `#E6B35A` | External actors (Internet, AWS DR). |
138-
139-
### Canonical edge palette (indexed `linkStyle`)
140-
141-
```text
142-
%% physical / network — solid bright green
143-
linkStyle 0,1,2 stroke:#4FB3A9,stroke-width:2px;
144-
145-
%% data / telemetry — dashed coral
146-
linkStyle 3,4 stroke:#E06B4A,stroke-width:2px,stroke-dasharray:4 3;
147-
148-
%% control / provisioning — solid paper, lower weight
149-
linkStyle 5 stroke:#F4EFE6,stroke-width:1.5px;
150-
151-
%% external / DR — dotted amber
152-
linkStyle 6 stroke:#E6B35A,stroke-width:1.5px,stroke-dasharray:2 4;
153-
154-
%% abort / failure — dashed dark coral
155-
linkStyle 7 stroke:#C25638,stroke-width:1.5px,stroke-dasharray:2 4;
156-
```
157-
158-
### Fun touches (consistent across the site)
159-
160-
Within the canonical palette, these are **encouraged** for personality:
161-
162-
- **Mix node shapes** purposefully — stadiums for processes, cylinders
163-
for stores, diamonds for decisions, circles for external actors.
164-
Variety helps readers parse at a glance.
165-
- **Short labels.** `claude process`, not `the Claude Code subprocess`.
166-
Two lines max (use `<br/>` sparingly).
167-
- **Edge labels are fine** when they add information (`"renew leases"`,
168-
`"hands off"`, `"applies"`). Skip them when the chain is obvious.
169-
- **FontAwesome icons** in node labels where they reinforce the shape:
170-
`[fa:fa-shield Security]`, `[fa:fa-server Host]`. Stick to filled
171-
variants for visual weight.
172-
173-
## Mermaid — layout rules
174-
175-
Before emitting any mermaid block, run the four checks below. If a
176-
diagram fails ANY check, redesign it before writing the fence.
177-
178-
### Rule 1 · One narrative shape per diagram
179-
180-
Decide which of these four shapes the data IS, then commit to it. If you
181-
can't pick one, you have two concerns — split into two diagrams.
182-
183-
- **LINEAR CHAIN**`A → B → C → D → E`. Use `flowchart LR`. No subgraphs
184-
for "roles" or "phases" (they always cause zigzag). To show role/owner,
185-
color nodes via `classDef`. Don't put them in columns.
186-
- **PARALLEL CONVERGENCE** — two chains that join at the end. Use
187-
`flowchart LR`. Declare the longer chain first (its nodes appear higher
188-
in source). ELK will rank the shorter chain on the second row.
189-
- **HIERARCHY / TREE** — a parent with grouped children. Use `flowchart TB`.
190-
Children grouped in subgraphs with `direction LR`. Cap subgraph contents
191-
at 5 nodes — overflow gets a second subgraph at the same rank.
192-
- **HUB AND SPOKES** — one central node connected to 4–8 leaves. Use
193-
`flowchart LR`, put leaves in a single subgraph with `direction TB`. Do
194-
not draw all edges from hub — chain leaves inside the subgraph with
195-
invisible `~~~` links so they stack, then one edge hub → first leaf.
196-
197-
### Rule 2 · Subgraphs are for THINGS that live together, not for ROLES
198-
199-
Subgraphs add a visual box. If the box doesn't represent something that
200-
physically or logically co-locates, do NOT make it a subgraph.
201-
202-
- **Forbidden** subgraph names: `Human`, `AI`, `Automation`, `Phase 1`,
203-
any role or temporal phase. A workflow that hands off
204-
Human → AI → Human → AI draws a zigzag because arrows cross subgraph
205-
boundaries N times; visual complexity goes O(n) → O(n²).
206-
- **Allowed** subgraph names — actual co-location: `Proxmox cluster`,
207-
`Cribl tier`, `UniFi network`, `AWS DR`, `Edge`, `Infrastructure`,
208-
`Configuration`, `Nix`, `AI Development`, `Observability`.
209-
- For role/owner: use `classDef`, color the nodes. The chain stays linear.
210-
211-
```text
212-
classDef human fill:#FBF7EE,stroke:#2F7E78,stroke-width:2px;
213-
classDef ai fill:#FFE7DC,stroke:#E06B4A,stroke-width:2px;
214-
classDef auto fill:#F4EFE6,stroke:#0B1D2A,stroke-width:1.5px;
215-
class H1,H3 human
216-
class A1,A2,A3 ai
217-
class T1,T2,T3 auto
218-
```
219-
220-
### Rule 3 · Density caps — measured, not vibed
221-
222-
- Max **5 nodes per rank** (per LR column or TB row).
223-
- Max **5 nodes inside any single subgraph**. 6+ → split into two
224-
subgraphs at the same rank.
225-
- Max **12 nodes per diagram total**. Past 12, you have two diagrams.
226-
- Max **ONE subgraph boundary per edge**. An edge that crosses two
227-
boundaries means a subgraph is in the wrong place; reorder source
228-
declarations until each edge crosses ≤1 boundary.
229-
230-
Aspect-ratio sanity check (mentally render before emitting):
231-
232-
- Wider than 2.5:1 → outer direction is wrong (use TB instead)
233-
- Taller than 1:1.2 → too many siblings somewhere (cap at 5)
234-
- Goal: between 16:9 and 4:3.
235-
236-
### Rule 4 · `classDef` always, `linkStyle` by index
237-
238-
- **Never emit per-node `style` statements.** Always use `classDef`. A
239-
diagram with 8 identical `style X fill:...` lines is a code smell — the
240-
8 nodes share a category; give them a class.
241-
- **Never emit a global `linkStyle default stroke:#E06B4A`**. It paints
242-
every edge the same colour and throws away semantic differentiation.
243-
Color edges by what they represent, using indexed `linkStyle`:
244-
245-
```text
246-
%% edges 0-2 are deployment, edges 3-5 are telemetry
247-
linkStyle 0,1,2 stroke:#2F7E78,stroke-width:2px;
248-
linkStyle 3,4,5 stroke:#E06B4A,stroke-width:2px,stroke-dasharray:4 3;
249-
```
250-
251-
Edge index = declaration order, zero-based. Count carefully.
252-
253-
Standard edge palette for this site:
254-
255-
| Meaning | Style | Colour |
256-
| --- | --- | --- |
257-
| Physical / network | solid | `#2F7E78` (deep green) |
258-
| Data / telemetry | dashed | `#E06B4A` (coral) |
259-
| Control / provisioning | solid, lower weight | `#0B1D2A` (ink) |
260-
| External / DR | dotted | `#E6B35A` (amber) |
261-
262-
### Self-check before emitting
263-
264-
- [ ] Diagram is one of the four shapes (chain / convergence / hierarchy / hub)
265-
- [ ] No subgraph is named for a role (Human, AI, Phase 1, etc.)
266-
- [ ] Every rank ≤5 nodes, every subgraph ≤5 nodes, total ≤12
267-
- [ ] Every edge crosses ≤1 subgraph boundary
268-
- [ ] Zero `style` statements; all visual grouping via `classDef`
269-
- [ ] Zero `linkStyle default`; edges colored by semantic category
270-
- [ ] Mentally rendered aspect ratio between 4:3 and 16:9
271-
272-
If ANY box is unchecked, redesign before responding. Show the self-check
273-
as a comment block ABOVE the mermaid fence so a human can verify your
274-
reasoning:
275-
276-
```text
277-
%% Shape: linear chain. Boundary crossings: 0. Ranks: 9×1.
278-
%% Aspect: ~3:1 (LR). Pass.
279-
```
280-
281-
### When NOT to use Mermaid
282-
283-
If the content is a flat list, a comparison, or sequential steps without
284-
branching, prefer the native Mintlify primitive instead. Mermaid is for
285-
shapes; tables and Steps are for everything else.
286-
287-
| Use | When |
288-
| --- | --- |
289-
| `<Steps>` | Sequential process where each step is one action |
290-
| Table | Categorisation, comparison, "X column maps to Y column" |
291-
| Mermaid | One of the four shapes above; structure ≥ 4 nodes with real edges |
292-
| Prose with bold leads | Relationships that read better as a paragraph |
293-
294-
## Mermaid — drill-down links
295-
296-
Make diagram nodes navigable. Mintlify honors Mermaid's `click`
297-
directive: each node gets a pointer cursor, a hover tooltip, and
298-
navigates on click. This is the canonical way to get "zoom in to a
299-
detail page" behaviour on this site — no custom components, no SVG
300-
export, no JavaScript.
301-
302-
### When to add clicks
303-
304-
Add `click` whenever a node represents a topic that has its own
305-
detail page on this site or its own canonical external URL (a repo,
306-
a dashboard, a vendor doc). This is **the default for context,
307-
overview, and hub diagrams** — not an optional embellishment.
308-
309-
Skip clicks for: nodes that don't map to a real destination (a
310-
transient process, an abstract concept like "Code" or "Ship"), or
311-
destinations that are still TODO and would 404.
312-
313-
### Canonical syntax — INTERNAL links only
314-
315-
Use only this form. One `click` per line. Always include a tooltip —
316-
for hover-only users it's the only signal of where the click goes.
317-
318-
```text
319-
click NodeId "/path/to/internal/page" "Short hover tooltip"
320-
```
321-
322-
Place the `click` block AFTER all `classDef` definitions and `class`
323-
assignments, and BEFORE any `linkStyle` lines.
324-
325-
### External URLs — do NOT click them from the diagram
326-
327-
Mermaid has open bugs
328-
([#3077](https://github.com/mermaid-js/mermaid/issues/3077),
329-
[#5550](https://github.com/mermaid-js/mermaid/issues/5550)) where
330-
`_blank` is parsed but silently dropped from the rendered SVG.
331-
Clicking an external link on a node navigates the current tab away —
332-
the diagram disappears, the back button is the only way home.
333-
334-
Workaround: put external links in a **table** or **CardGroup**
335-
directly under the diagram. Mintlify automatically adds
336-
`target="_blank" rel="noreferrer"` to external markdown anchors, so
337-
those open in a new tab correctly.
338-
339-
Inside the Mermaid block, click ONLY the internal nodes; leave the
340-
external-pointing nodes without a `click` directive and add an HTML
341-
comment naming where the repo lives:
342-
343-
```text
344-
flowchart LR
345-
Tool([Tool]) --> Pack([cc-edge-foo])
346-
click Tool "/observability/overview" "Tool overview"
347-
%% No click on Pack — external repo lives in the table below.
348-
```
349-
350-
Then the table directly under the diagram carries the external link:
351-
352-
```text
353-
| Repo | Notes |
354-
| --- | --- |
355-
| [cc-edge-foo](https://github.com/owner/cc-edge-foo) | What it does |
356-
```
357-
358-
When the Mermaid bugs are fixed upstream, this convention will
359-
expand to allow external clicks; until then, internal-only.
360-
361-
### Self-check addition
362-
363-
Append these to the existing self-check before emitting any context,
364-
overview, or hub diagram:
365-
366-
- [ ] Every node whose label names a topic with a detail page has a `click` line
367-
- [ ] All `click` URLs are site-relative paths (`/security/overview`), never external `https://...`
368-
- [ ] External repo URLs live in a table or CardGroup beside the diagram, NOT in `click` directives
369-
- [ ] Tooltips are ≤40 chars and describe the destination (not the node)
370-
- [ ] No `click` points at a page that doesn't exist yet (would 404)
371-
- [ ] CI Mermaid validation passes (`./scripts/validate-mermaid.sh` from repo root)
372-
373-
### Example
374-
375-
```text
376-
flowchart LR
377-
Ovr([Overview]) --> Detail([Detail page])
378-
classDef hop fill:#102937,stroke:#4FB3A9,stroke-width:2px,color:#F4EFE6;
379-
class Ovr,Detail hop
380-
click Ovr "/overview" "Read the full overview"
381-
click Detail "/overview/detail" "The deep dive"
382-
```
383-
384-
### When NOT to use clicks
385-
386-
- **Pure sequence / timeline diagrams** where every node is a stage
387-
in one flow (e.g. CI step "Lint") — clicks would imply each stage
388-
has its own page when the whole pipeline is one page.
389-
- **Diagrams in repo READMEs that render on GitHub.** GitHub's
390-
Mermaid renderer honors `click` differently and absolute URLs are
391-
required there. Keep site-relative click diagrams on
392-
docs.jacobpevans.com; if a README needs an interactive diagram,
393-
link out to the relevant docs page instead.
88+
- [`conventions/mermaid-style`](conventions/mermaid-style.mdx) — the byte-for-byte
89+
theme directive, shape vocabulary, `classDef` and `linkStyle` palettes, the four
90+
narrative shapes, and density caps.
91+
- [`conventions/mermaid-links`](conventions/mermaid-links.mdx) — making diagram
92+
nodes navigable with the `click` directive, and the external-URL workaround.
39493

39594
## Phases
39695

conventions/diagramming.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Required for any repo with meaningful architecture. Stale diagrams are worse tha
3333

3434
## Style
3535

36-
The canonical Mermaid style guide for the docs site lives in this repo's [`AGENTS.md`](https://github.com/JacobPEvans/docs/blob/main/AGENTS.md). The byte-for-byte theme directive, shape vocabulary, semantic `classDef` palette, indexed `linkStyle` palette, and the four narrative shapes (linear chain, parallel convergence, hierarchy, hub and spokes) are reusable across every repo that publishes diagrams alongside its code.
36+
The canonical Mermaid style guide for the docs site lives in [`conventions/mermaid-style`](/conventions/mermaid-style), with node-navigation rules in [`conventions/mermaid-links`](/conventions/mermaid-links). The byte-for-byte theme directive, shape vocabulary, semantic `classDef` palette, indexed `linkStyle` palette, and the four narrative shapes (linear chain, parallel convergence, hierarchy, hub and spokes) are reusable across every repo that publishes diagrams alongside its code.
3737

3838
Highlights:
3939

0 commit comments

Comments
 (0)