name: mermaid-diagram-authoring description: |- Author clean Mermaid diagrams that render correctly in 1-3 tries. Use when creating or editing any .mmd diagram for SVG output. Use when you need to visualize architecture, pipelines, flows, or component relationships. compatibility: claude-code, cursor, opencode, gemini-cli, codex-cli allowed-tools: bash, read, write, edit, grep metadata: companion-script: scripts/tools/render-mermaid.sh handoffs: "" trigger-phrases: > diagram, mermaid, mmd, SVG, visualize, flow, architecture diagram, pipeline, render diagram, chart, graph pattern: tool-wrapper
bundle: build
Mermaid Diagram Authoring
Principle
Every diagram starts as a .mmd file. SVGs are generated artifacts.
Never hand-edit SVGs. Fix the .mmd, re-render.
Tool
Use render-mermaid.sh for all rendering:
# Render single file
bash scripts/tools/render-mermaid.sh -i docs/diagrams/flow.mmd
# With options
bash scripts/tools/render-mermaid.sh -i docs/arch.mmd -o docs/arch.svg \
-w 1200 -t dark -b transparent
# Quick verification (quiet mode)
bash scripts/tools/render-mermaid.sh -i docs/diagram.mmd -q
# View auto-detected Chrome config (for debugging)
bash scripts/tools/render-mermaid.sh --puppeteer-only
Fast iteration loop (1-3 tries target)
Write .mmd → Render → Open SVG → Fix .mmd → Re-render
try 1 try 1 review try 2 try 2
- Try 1: Write complete .mmd, render, open SVG. 80% chance of success.
- Try 2: Fix subgraph alignment, edge routing, or label overflow. Re-render. 95% chance.
- Try 3: Tune spacing, font size, or layout direction. 99%+ success.
If you're on try 4+, you're overcomplicating the diagram. Simplify it.
Diagram Type Selection
| You want to show... | Use this Mermaid type |
|---|---|
| Process flow, decision branches | flowchart |
| Component hierarchy / system layers | flowchart TB |
| Left-to-right pipeline stages | flowchart LR |
| Service-to-service interaction over time | sequenceDiagram |
| Class / interface / type relationships | classDiagram |
| State transitions | stateDiagram-v2 |
| Entity-relationship model | erDiagram |
| Timeline of events / project phases | gantt |
Mermaid Authoring Rules (for 1-try success)
1. Always name your subgraphs explicitly
❌ BAD — unnamed subgraph, no direction:
subgraph Pipeline
A --> B
end
✅ GOOD — named + direction TB:
subgraph PIPELINE["Decode Pipeline"]
direction TB
A["Step One"] --> B["Step Two"]
end
Why: Unnamed subgraphs use auto-layout that often overlaps. direction TB
forces top-to-bottom within the subgraph, preventing horizontal bleed.
2. Use explicit direction TB in every subgraph (for TB/TD parents)
Empirically proven. The default subgraph layout in a flowchart TB parent
is horizontal (side-by-side). Explicit direction TB forces vertical
(stacked). The difference is measurable in SVG output coordinates:
TB parent, NO direction TB in subgraph: TB parent, WITH direction TB:
Node A x=104 y=70 ← same row Node A x=102 y=72
Node B x=297 y=70 ← same row Node B x=102 y=201 ↓
Node C x=490 y=70 ← same row Node C x=102 y=330 ↓
→ HORIZONTAL layout → VERTICAL layout
Without direction TB, sibling nodes inside a subgraph of a TB parent are
placed side-by-side horizontally, which causes crossed lines, overlap,
and subgraph boxes that don't contain their children.
Every subgraph in a flowchart TB (or flowchart TD) diagram needs:
subgraph SUBSYS["Subsystem Name"]
direction TB # ← REQUIRED for TB/TD parents
N1 --> N2
end
Exception: In flowchart LR parents, subgraphs default to vertical
stacking automatically. The direction TB statement is harmless but
unnecessary in LR parents.
Inverse: direction LR inside a subgraph of a TB parent forces
horizontal layout inside that subgraph — useful for pipeline stages.
3. Use quoted labels for display names
❌ BAD — unquoted label, fragile:
subgraph RAW[Raw Decoders]
✅ GOOD — double-quoted:
subgraph RAW["Raw Decoders (6 engines)"]
❌ BAD — node with spaces unquoted:
A --> Size Guard
✅ GOOD — always quote node labels:
A["Decode Request (filePath)"] --> B["Size Guard (< 100 MB)"]
Why: Spaces, special chars (<, >, (, )), and long text break
parsing unless quoted with double quotes.
4. Keep subgraphs flat (max 2 levels deep)
Empirically proven: 4-level nesting renders without crashing, but subgraph boxes overlap visually and the layout is hard to read. All 4 level boxes render at x=8 (left-aligned) with decreasing sizes — they appear as concentric rectangles rather than proper nested containers.
❌ TOO DEEP — 3+ levels of nested subgraphs:
subgraph A["Layer 1"]
subgraph B["Layer 2"]
subgraph C["Layer 3"]
N1 --> N2
end
end
end
✅ BETTER — 2 levels max, flatten inner groups:
subgraph A["Layer 1"]
N1["Sub A1"] --> N2["Sub A2"]
subgraph B["Layer 2"]
N3 --> N4
end
end
Why: Deeply nested subgraphs cause Mermaid's layout engine to produce overlapping boxes and misaligned edges. 2 levels is the sweet spot.
5. Use TB (top-to-bottom) as default for documentation
flowchart TB # ← Use TB for README/docs diagrams
flowchart LR # ← Use LR only for horizontal pipelines
TB produces taller, narrower diagrams that fit well in documentation. LR is good for CI/CD pipelines and left-to-right process stages.
6. Avoid more than 25 nodes per diagram
If you need more than 25 nodes, split into multiple diagrams. A diagram with 30+ nodes in subgraphs will have overlapping issues.
7. Use --- config header for advanced themes
---
config:
theme: neutral
flowchart:
curve: basis
---
flowchart TB
A --> B
Supported config options:
theme:default,dark,forest,neutral(match to doc background)flowchart.curve:basis(smooth),linear,step(sharp corners)fontFamily: set to match your doc font
8. Subgraph naming convention for cross-reference
Use this naming convention:
subgraph SUBSYS_NAME["Display Name"]
Where SUBSYS_NAME is an UPPER_SNAKE identifier and "Display Name" is
the human-readable label. This makes CSS-level targeting work and keeps
the source readable.
9. Layout tuning (when alignment still looks wrong)
If nodes overlap or edges cross after the first render:
| Problem | Fix |
|---|---|
| Subgraph boxes overlapping | Add direction TB to every subgraph |
| Nodes inside subgraph are horizontal | Add direction TB to that subgraph |
| Edges crossing each other | Reorder node definitions (top-to-bottom in source) |
| Long labels cut off | Add "..." around the label, or use <br> for line breaks |
| Diagram too wide | Change LR to TB, or reduce width with -w 600 |
| Diagram too tall | Change TB to LR, or split into two diagrams |
10. Use markdown-style nodes for multi-line labels
NODE1["
Line 1
Line 2
Line 3
"]
This creates a node with three lines. Useful for showing parameters or descriptions inside a node.
11. Use shape markers for semantic meaning
INPUT[/"File Input"/] # Stadium shape for I/O
DECISION{"Condition?"} # Rhombus for decisions
OUTPUT[/"Result"/] # Stadium for output
SUBPROCS(["Sub-processes"]) # Double-stadium for grouped processes
DATABASE[("Database")] # Cylinder for data stores
12. Edges between nodes in the same subgraph belong inside the subgraph
When two nodes are both declared inside the same subgraph and you want an edge between them, place the edge inside the subgraph too:
subgraph BOX["Correct"]
direction TB
N1["A"] --> N2["B"] # ← edge inside the subgraph
end
If you place the edge outside the subgraph, Mermaid may misroute it outside the subgraph boundary, causing visual confusion. The renderer still works, but the edge path may clip through other subgraph boxes.
Exception: edges between nodes in DIFFERENT subgraphs must be outside both subgraphs (at the top level).
Verification Checklist
Before declaring a diagram done, verify:
- Rendered SVG opens without layout bugs
- No overlapping nodes or subgraph boxes
- All labels are fully visible (not truncated)
- Edge arrows reach their target nodes
- Subgraph boundaries contain their children
- Theme matches document background (dark doc →
-t dark) - SVG has no HTML comment timestamps (our script strips these)
- SVG has
viewBoxattribute (ensures responsiveness) - SVG ends with valid
</svg>tag - Both
.mmdand.svgare committed
Troubleshooting
"mmdc: command not found"
npm install -g @mermaid-js/mermaid-cli
"No Chrome executable found"
The script auto-detects from ~/.cache/puppeteer/. If it fails:
npm install -g puppeteer
# Or set explicit path:
CHROME_PATH=/usr/bin/chromium bash scripts/tools/render-mermaid.sh -i in.mmd
SVG renders with white background instead of transparent
Pass -b transparent to the render command. Our default is transparent.
Diagram is too small / too large
Adjust with -w <pixels>. Default is 800. For wide diagrams: -w 1200.
For small diagrams: -w 600.
Subgraph completely misaligned
This is the #1 Mermaid bug. Fix:
- Ensure
direction TBin every subgraph of a TB parent (proven: without it, sibling nodes go horizontal instead of vertical) - Ensure no subgraph is 3+ levels deep (proven: 4 levels render but boxes overlap and layout is unreadable)
- Ensure edges between nodes in the same subgraph are placed inside that subgraph, not at the top level
- If still misaligned, flatten the structure and use inline node names instead of nested subgraphs
Parser error: "Expecting 'direction_tb', got 'end'"
This occurs when Mermaid's parser reaches end inside a subgraph but
hasn't found a direction statement. The most common cause is placing
edges inside a subgraph when sibling nodes also exist without explicit
direction. Fix: add direction TB on the line after the subgraph
opening, or restructure so nodes use chained edges (N1 --> N2 --> N3)
instead of standalone sibling declarations.
SVG nodes are side-by-side when they should be stacked
You have a flowchart TB diagram but a subgraph's sibling nodes are
horizontal. Fix: add direction TB inside that subgraph. This is
the proven #1 cause of horizontal-vertical confusion.
Learning from ithmb-codec
The diagrams in the ithmb-codec repo (architecture.mmd, pipeline.mmd,
decode-pipeline-test.mmd) demonstrate production-quality Mermaid. Key
patterns to adopt:
- Named subgraphs with
direction TB→ prevents alignment drift flowchart TBfor documentation (taller, narrower, fits README)flowchart LRfor pipeline stages (wider, shows left-to-right flow)- Markdown-style nodes for multi-line labels → keeps node width manageable
- Shape markers (
/"/,{"?"},[()],(["..."])) → semantic readability - Config header for theme control → consistent look across diagrams
Adopt these patterns and you'll typically get the right diagram on the first render.
Quick Reference
# Minimal — create .mmd, then:
bash scripts/tools/render-mermaid.sh -i file.mmd
# Full-featured:
bash scripts/tools/render-mermaid.sh \
-i file.mmd \
-o file.svg \
-w 1000 \
-t dark \
-b transparent