Adding a Mermaid diagram
A diagram in these docs is not an image. It is a plain fenced code block written directly in the page body:
```mermaidflowchart LR A[Prompt] --> B[Generated master]```The astro-mermaid integration
(^2.1.0, wired in astro.config.mjs) finds every fenced mermaid block at build time and
swaps it for a client-side render. There is no import, no config edit, and no .png to
commit — you write text, the reader gets a diagram that re-themes with the light/dark
toggle.
How rendering works
Section titled “How rendering works”The integration is listed before starlight() in
astro.config.mjs so it can transform the
fence before Starlight renders the page. Its config is the only thing that governs theming,
and you never touch it:
theme: 'default'— the base Mermaid theme.autoTheme: true— the render follows thedata-themeattribute Starlight stamps on<html>. When a reader flips the header toggle, every diagram re-renders in the new theme. This is why you must write theme-neutral diagrams (see below).mermaidConfig.flowchart.curve: 'basis'— the house edge style for flowcharts.
Because rendering is client-side, a diagram is JavaScript that runs in the browser — it is not baked into the HTML. That is invisible in normal use; it only matters if you are reading a page with scripting disabled.
Add a diagram
Section titled “Add a diagram”-
Pick the diagram type. The fleet’s pages use four:
flowchart(architecture and data flow),sequenceDiagram(request lifecycles — turn onautonumber),erDiagram(the data model), andstateDiagram-v2(the money path). Use whichever Mermaid grammar fits; the integration renders all of them. -
Open a fenced
mermaidblock in the page body where the diagram belongs. No import, no frontmatter change. -
Write the Mermaid source. Give each node a tier class with the
:::classNamesuffix (for example`GW["core-gateway-consumer"]:::gateway`) and paste the fiveclassDeflines from the tier legend at the bottom of the block. -
Preview it. Run the site (
npm run dev) and open the page — the diagram renders in the browser. Toggle light/dark in the header and confirm it stays legible in both. -
Reuse before you redraw. Most diagrams already exist. Copy the source from a sibling page (for example the hero flowchart on the mental model or the sequence on the request lifecycle) and adapt it — but fix any stale labels you inherit.
Colour by tier
Section titled “Colour by tier”Every architecture diagram uses one five-tier colour legend — indigo frontend, blue gateways, purple data plane, green workers, amber external — so a node’s colour tells you what kind of thing it is at a glance. The classes are defined once per diagram and are the only fills you should use, because they are the only ones tested for contrast in both themes:
classDef frontend fill:#6366f1,color:#fff,stroke:#4338caclassDef gateway fill:#0ea5e9,color:#fff,stroke:#0369a1classDef data fill:#8b5cf6,color:#fff,stroke:#6d28d9classDef worker fill:#10b981,color:#fff,stroke:#047857classDef external fill:#f59e0b,color:#111,stroke:#b45309The Diagram conventions reference is the source of truth for what each tier means and which service belongs in it. Don’t invent per-node colours — an un-tiered rainbow reads as noise, and hand-picked fills usually fail contrast in one of the two themes.
Worked example
Section titled “Worked example”Here is a small, real diagram — the generation path in miniature. First the source you write:
```mermaidflowchart LR U(["Browser"]):::frontend GW["core-gateway-consumer<br/>price · reserve · queue"]:::gateway DB[("core-database<br/>sole Postgres door")]:::data WK["core-tool-sansaarm"]:::worker PROV["Sansaarm API"]:::external
U -->|gRPC consumer/v1| GW GW -->|QueueTask| DB WK -->|ClaimNextTask| DB WK --> PROV
classDef frontend fill:#6366f1,color:#fff,stroke:#4338ca classDef gateway fill:#0ea5e9,color:#fff,stroke:#0369a1 classDef data fill:#8b5cf6,color:#fff,stroke:#6d28d9 classDef worker fill:#10b981,color:#fff,stroke:#047857 classDef external fill:#f59e0b,color:#111,stroke:#b45309```And here is exactly that block, rendered — toggle the page theme and watch it follow:
flowchart LR
U(["Browser"]):::frontend
GW["core-gateway-consumer<br/>price · reserve · queue"]:::gateway
DB[("core-database<br/>sole Postgres door")]:::data
WK["core-tool-sansaarm"]:::worker
PROV["Sansaarm API"]:::external
U -->|gRPC consumer/v1| GW
GW -->|QueueTask| DB
WK -->|ClaimNextTask| DB
WK --> PROV
classDef frontend fill:#6366f1,color:#fff,stroke:#4338ca
classDef gateway fill:#0ea5e9,color:#fff,stroke:#0369a1
classDef data fill:#8b5cf6,color:#fff,stroke:#6d28d9
classDef worker fill:#10b981,color:#fff,stroke:#047857
classDef external fill:#f59e0b,color:#111,stroke:#b45309
Traps and house rules
Section titled “Traps and house rules”Diagram types in use reference
Section titled “Diagram types in use ”| Grammar | Used for | Example page |
|---|---|---|
flowchart |
Architecture, data flow | System overview |
sequenceDiagram (autonumber) |
Request lifecycles | Request lifecycle |
erDiagram |
The data model | Data model |
stateDiagram-v2 |
State machines (the money path) | Data model |
Related
Section titled “Related”- Diagram conventions — what each of the five tiers means
- Authoring conventions — asides, badges, and the secret-safety rule
- Running & deploying the docs — preview your diagram with
npm run dev - The 60-second mental model — the canonical tiered flowchart to copy from