Skip to content

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:

Somewhere in your .mdx page
```mermaid
flowchart 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.

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 the data-theme attribute 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.

  1. Pick the diagram type. The fleet’s pages use four: flowchart (architecture and data flow), sequenceDiagram (request lifecycles — turn on autonumber), erDiagram (the data model), and stateDiagram-v2 (the money path). Use whichever Mermaid grammar fits; the integration renders all of them.

  2. Open a fenced mermaid block in the page body where the diagram belongs. No import, no frontmatter change.

  3. Write the Mermaid source. Give each node a tier class with the :::className suffix (for example `GW["core-gateway-consumer"]:::gateway`) and paste the five classDef lines from the tier legend at the bottom of the block.

  4. 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.

  5. 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.

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:

Paste these at the bottom of every architecture diagram
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

The 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.

Here is a small, real diagram — the generation path in miniature. First the source you write:

A tiered flowchart
```mermaid
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
```

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

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