Theme
← Home

Rendering Mermaid diagrams: options and trade-offs

On this page

Mermaid lets you write a diagram as text and keep it next to the text it explains. But Mermaid lays out diagrams by measuring text in a real browser. A static site has three ways to deal with that.

The three options

Option When it draws JS sent to readers Build needs Dark mode
Draw in the browser On page load ~650 KB minified (~165 KB gzipped), only on diagram pages Nothing Re-draw with a dark theme
Draw at build time (rehype-mermaid) During the build None Headless Chromium (Playwright) Two SVGs per diagram
Pre-render by hand (mermaid-cli) When you run it None Nothing for the site build; Chromium on your machine Two SVGs per diagram

1. Draw in the browser

Leave the Mermaid source in the HTML and let a script turn it into SVG.

  • Pros: No build dependencies. Writing a diagram means writing a code block, nothing more. Diagrams can re-draw when the reader switches colour scheme.
  • Cons: Mermaid is large, and each diagram type adds its own code on top, usually 20–120 KB. The diagram appears a moment after the page loads. Readers without JavaScript see the source text.

2. Draw at build time

The rehype-mermaid plugin starts a headless browser during the build and swaps each block for an inline SVG. Astro 7 turns Markdown into HTML with Sätteri, which doesn’t run rehype plugins, so you must first switch to the unified() processor (@astrojs/markdown-remark).

  • Pros: No JavaScript for readers; diagrams appear instantly.
  • Cons: Every build (local, CI, and Vercel) must download and run Chromium. Builds get slower and more fragile, and dark mode needs a second SVG per diagram.

3. Pre-render by hand

Run mermaid-cli yourself and commit the SVG files.

  • Pros: No JavaScript for readers, and the site build needs nothing extra. Your own machine still needs Chromium, which mermaid-cli downloads through Puppeteer.
  • Cons: The source and the image live apart and drift. Every edit needs a manual export.

What this blog does

This blog draws diagrams in the browser, but only on pages that contain one. The build marks each mermaid block so the code highlighter skips it; a small script then loads Mermaid on demand:

flowchart LR
  A[MDX file] --> B{mermaid block?}
  B -- yes --> C["pre.mermaid (left as text)"]
  B -- no --> D[Syntax highlighter colours it]
  C --> E[Browser loads Mermaid on demand]
  E --> F[SVG diagram]

Here is what happens when you open this page:

sequenceDiagram
  actor R as Reader
  participant B as Browser
  participant S as Web server
  R->>B: Open the post
  B->>S: Get the page
  S-->>B: HTML and a small page script
  B->>B: Script finds a pre.mermaid block
  B->>S: Get Mermaid files (only on diagram pages)
  S-->>B: Mermaid code
  B->>R: Show the diagram in light or dark theme
  R->>B: Switch OS to dark mode
  B->>R: Re-draw in dark theme

Pages without diagrams load none of this.

If a diagram page feels slow, pre-render that one diagram with mermaid-cli; the others can keep drawing in the browser.