Stedefast

Plugins

Mermaid

3 min read

/plugin-mermaid renders fenced ```mermaid code blocks to inline SVG at build time using mermaid-isomorphic. No Mermaid JavaScript is shipped to the browser — the SVG is embedded directly in the HTML output.

Installation

pnpm add /plugin-mermaid

Note: mermaid-isomorphic uses Playwright internally to render diagrams in a headless Chromium browser. On first install, Playwright will download a Chromium binary (~150 MB). This can be slow on CI — see Performance below.

Basic setup

// stedefast.config.ts
import { defineConfig } from "@stedefast/core";
import { MermaidPlugin } from "/plugin-mermaid";

export default defineConfig({
  // ...
  plugins: [
    MermaidPlugin({ theme: "default" }),
  ],
});

Any fenced ```mermaid block in your Markdown will be rendered to an inline SVG:

```mermaid
flowchart LR
  A[Start] --> B{Decision}
  B -->|Yes| C[Continue]
  B -->|No| D[Stop]
```

The output is wrapped in a <figure class="sf-diagram"> element.

Supported diagram types

All Mermaid diagram types are supported. A few examples:

Flowchart

```mermaid
flowchart TD
  A[User] --> B[Browser]
  B --> C[CDN]
  C --> D[Origin]
```

Sequence diagram

```mermaid
sequenceDiagram
  participant Browser
  participant Worker
  Browser->>Worker: POST /submit
  Worker-->>Browser: 200 OK
```

Class diagram

```mermaid
classDiagram
  class StedefastPlugin {
    +name: string
    +rehypePlugins: PluggableList
    +headAssets: HeadAssets
  }
```

State diagram

```mermaid
stateDiagram-v2
  [*] --> Idle
  Idle --> Building: build()
  Building --> Done: success
  Building --> Error: failure
  Done --> [*]
```

ER diagram

```mermaid
erDiagram
  POST ||--o{ COMMENT : has
  POST {
    string slug
    string title
  }
  COMMENT {
    string body
    string author
  }
```

Gantt chart

```mermaid
gantt
  title Project Timeline
  section Phase 1
    Research :a1, 2026-01-01, 14d
    Design   :a2, after a1, 7d
  section Phase 2
    Build    :a3, after a2, 21d
```

Pie chart

```mermaid
pie title Traffic Sources
  "Organic" : 60
  "Direct" : 25
  "Referral" : 15
```

Themes

Mermaid ships four built-in themes:

Theme Description
default Light, neutral colour palette
dark Dark background variant
neutral Monochrome, minimal
forest Green-tinted

Pass theme to select one:

MermaidPlugin({ theme: "neutral" })

Dual light/dark themes

For sites with light and dark colour modes, use themes to render two SVGs and swap them via CSS:

MermaidPlugin({
  themes: {
    light: "default",
    dark: "dark",
  },
})

The plugin renders both SVGs and emits:

<figure class="sf-diagram">
  <span class="sf-diagram-light"><!-- light SVG --></span>
  <span class="sf-diagram-dark"><!-- dark SVG --></span>
</figure>

It also automatically injects the following CSS into every page <head>:

.sf-diagram-dark { display: none; }
@media (prefers-color-scheme: dark) {
  .sf-diagram-light { display: none; }
  .sf-diagram-dark { display: block; }
}

If your theme uses a manual dark mode class (e.g. .dark on <html>), add this to your theme/styles/global.css instead:

.sf-diagram-dark { display: none; }
.dark .sf-diagram-light { display: none; }
.dark .sf-diagram-dark { display: block; }

Options reference

Option Type Default Description
theme string "default" Mermaid theme for single-theme mode. One of "default", "dark", "neutral", "forest". Mutually exclusive with themes.
themes { light: string; dark: string } Dual theme mode — renders two SVGs and swaps on prefers-color-scheme. Mutually exclusive with theme.
backgroundColor string "transparent" Background colour applied to rendered SVGs via Mermaid's themeVariables.

Error handling

If a diagram fails to render (invalid syntax, unsupported diagram type), the plugin logs a warning to stderr and leaves the original <pre><code class="language-mermaid"> block in place. The build continues without failing.

Performance

The first build will be slow because mermaid-isomorphic launches a Chromium process via Playwright. Subsequent diagrams in the same build are faster — the browser instance is reused across all diagrams on the page.

Identical diagrams (same source text and theme) are cached in memory within a single build invocation to avoid redundant renders.

CI caching: To avoid re-downloading Chromium on every CI run, cache the Playwright browser cache directory. For GitHub Actions:

- uses: actions/cache@v4
  with:
    path: ~/.cache/ms-playwright
    key: playwright-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}