beautiful-mermaid

GitHub

Technical documentation and AI CheatSheet for lukilabs/beautiful-mermaid

8,924 stars TypeScript Markdown CodeWiki
AI Prompts & Endpoints
CodeWiki Knowledge Base

Repository: lukilabs/beautiful-mermaid


Stars: 8764

README.md

<div align="center">

beautiful-mermaid

Render Mermaid diagrams as beautiful SVGs or ASCII art

Ultra-fast, fully themeable, zero DOM dependencies. Built for the AI era.

!beautiful-mermaid sequence diagram example

![npm version](https://www.npmjs.com/package/beautiful-mermaid)
![License](LICENSE)

Live Demo & Samples

โ†’ Use it live in Craft Agents

</div>

---

Why We Built This

Diagrams are essential for AI-assisted programming. When you're working with an AI coding assistant, being able to visualize data flows, state machines, and system architectureโ€”directly in your terminal or chat interfaceโ€”makes complex concepts instantly graspable.

Mermaid is the de facto standard for text-based diagrams. It's brilliant. But the default renderer has problems:

- Aesthetics โ€” Might be personal preference, but wished they looked more professional
- Complex theming โ€” Customizing colors requires wrestling with CSS classes
- No terminal output โ€” Can't render to ASCII for CLI tools
- Heavy dependencies โ€” Pulls in a lot of code for simple diagrams

We built beautiful-mermaid at Craft to power diagrams in Craft Agents. It's fast, beautiful, and works everywhereโ€”from rich UIs to plain terminals.


The ASCII rendering engine is based on mermaid-ascii by Alexander Grooff. We ported it from Go to TypeScript and extended it. Thank you Alexander for the excellent foundation! (And inspiration that this was possible.)

Features

- 6 diagram types โ€” Flowcharts, State, Sequence, Class, ER, and XY Charts (bar, line, combined)
- Dual output โ€” SVG for rich UIs, ASCII/Unicode for terminals
- Synchronous rendering โ€” No async, no flash. Works with React useMemo()
- 15 built-in themes โ€” And dead simple to add your own
- Full Shiki compatibility โ€” Use any VS Code theme directly
- Live theme switching โ€” CSS custom properties, no re-render needed
- Mono mode โ€” Beautiful diagrams from just 2 colors
- Zero DOM dependencies โ€” Pure TypeScript, works everywhere
- Ultra-fast โ€” Renders 100+ diagrams in under 500ms

Installation

bash
npm install beautiful-mermaid

or


bun add beautiful-mermaid

or


pnpm add beautiful-mermaid

Quick Start

SVG Output

typescript
import { renderMermaidSVG } from 'beautiful-mermaid'

const svg = renderMermaidSVG(
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Action]
B -->|No| D[End]
)

Rendering is fully synchronous โ€” no await, no promises. The ELK.js layout engine runs synchronously via a FakeWorker bypass, so you get your SVG string instantly.

Need async? Use renderMermaidSVGAsync() โ€” same output, returns a Promise<string>.

ASCII Output

typescript
import { renderMermaidASCII } from 'beautiful-mermaid'

const ascii = renderMermaidASCII(graph LR; A --> B --> C)

text
โ”Œโ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”
โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚
โ”‚ A โ”‚โ”€โ”€โ”€โ”€โ–บโ”‚ B โ”‚โ”€โ”€โ”€โ”€โ–บโ”‚ C โ”‚
โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚
โ””โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”˜

---

React Integration

Because rendering is synchronous, you can use useMemo() for zero-flash diagram rendering:

tsx
import { renderMermaidSVG } from 'beautiful-mermaid'

function MermaidDiagram({ code }: { code: string }) {
const { svg, error } = React.useMemo(() => {
try {
return {
svg: renderMermaidSVG(code, {
bg: 'var(--background)',
fg: 'var(--foreground)',
transparent: true,
}),
error: null,
}
} catch (err) {
return { svg: null, error: err instanceof Error ? err : new Error(String(err)) }
}
}, [code])

if (error) return <pre>{error.message}</pre>
return <div dangerouslySetInnerHTML={{ __html: svg! }} />
}

Why this works well:
- No flash โ€” SVG is computed synchronously during render, not in a useEffect
- CSS variables โ€” Pass var(--background) etc. instead of hex colors. The SVG inherits from your app's CSS, so theme switches apply instantly without re-rendering
- Memoized โ€” Only re-renders when code changes

---

Theming

The theming system is the heart of beautiful-mermaid. It's designed to be both powerful and dead simple.

The Two-Color Foundation

Every diagram needs just two colors: background (bg) and foreground (fg). That's it. From these two colors, the entire diagram is derived using color-mix():

typescript
const svg = renderMermaidSVG(diagram, {
bg: '#1a1b26', // Background
fg: '#a9b1d6', // Foreground
})

This is Mono Modeโ€”a coherent, beautiful diagram from just two colors. The system automatically derives:

| Element | Derivation |
|---------|------------|
| Text | --fg at 100% |
| Secondary text | --fg at 60% into --bg |
| Edge labels | --fg at 40% into --bg |
| Faint text | --fg at 25% into --bg |
| Connectors | --fg at 50% into --bg |
| Arrow heads | --fg at 85% into --bg |
| Node fill | --fg at 3% into --bg |
| Group header | --fg at 5% into --bg |
| Inner strokes | --fg at 12% into --bg |
| Node stroke | --fg at 20% into --bg |

Enriched Mode

For richer themes, you can provide optional "enrichment" colors that override specific derivations:

typescript
const svg = renderMermaidSVG(diagram, {
bg: '#1a1b26',
fg: '#a9b1d6',
// Optional enrichment:
line: '#3d59a1', // Edge/connector color
accent: '#7aa2f7', // Arrow heads, highlights
muted: '#565f89', // Secondary text, labels
surface: '#292e42', // Node fill tint
border: '#3d59a1', // Node stroke
})

If an enrichment color isn't provided, it falls back to the color-mix() derivation. This means you can provide just the colors you care about.

CSS Custom Properties = Live Switching

All colors are CSS custom properties on the <svg> element. This means you can switch themes instantly without re-rendering:

javascript
// Switch theme by updating CSS variables
svg.style.setProperty('--bg', '#282a36')
svg.style.setProperty('--fg', '#f8f8f2')
// The entire diagram updates immediately

For React apps, pass CSS variable references instead of hex values:

typescript
const svg = renderMermaidSVG(diagram, {
bg: 'var(--background)',
fg: 'var(--foreground)',
accent: 'var(--accent)',
transparent: true,
})
// Theme switches apply automatically via CSS cascade โ€” no re-render needed

Built-in Themes

15 carefully curated themes ship out of the box:

| Theme | Type | Background | Accent |
|-------|------|------------|--------|
| zinc-light | Light | #FFFFFF | Derived |
| zinc-dark | Dark | #18181B | Derived |
| tokyo-night | Dark | #1a1b26 | #7aa2f7 |
| tokyo-night-storm | Dark | #24283b | #7aa2f7 |
| tokyo-night-light | Light | #d5d6db | #34548a |
| catppuccin-mocha | Dark | #1e1e2e | #cba6f7 |
| catppuccin-latte | Light | #eff1f5 | #8839ef |
| nord | Dark | #2e3440 | #88c0d0 |
| nord-light | Light | #eceff4 | #5e81ac |
| dracula | Dark | #282a36 | #bd93f9 |
| github-light | Light | #ffffff | #0969da |
| github-dark | Dark | #0d1117 | #4493f8 |
| solarized-light | Light | #fdf6e3 | #268bd2 |
| solarized-dark | Dark | #002b36 | #268bd2 |
| one-dark | Dark | #282c34 | #c678dd |

typescript
import { renderMermaidSVG, THEMES } from 'beautiful-mermaid'

const svg = renderMermaidSVG(diagram, THEMES['tokyo-night'])

Adding Your Own Theme

Creating a theme is trivial. At minimum, just provide bg and fg:

typescript
const myTheme = {
bg: '#0f0f0f',
fg: '#e0e0e0',
}

const svg = renderMermaidSVG(diagram, myTheme)

Want richer colors? Add any of the optional enrichments:

typescript
const myRichTheme = {
bg: '#0f0f0f',
fg: '#e0e0e0',
accent: '#ff6b6b', // Pop of color for arrows
muted: '#666666', // Subdued labels
}

Full Shiki Compatibility

Use any VS Code theme directly via Shiki integration. This gives you access to hundreds of community themes:

typescript
import { getSingletonHighlighter } from 'shiki'
import { renderMermaidSVG, fromShikiTheme } from 'beautiful-mermaid'

// Load any theme from Shiki's registry
const highlighter = await getSingletonHighlighter({
themes: ['vitesse-dark', 'rose-pine', 'material-theme-darker']
})

// Extract diagram colors from the theme
const colors = fromShikiTheme(highlighter.getTheme('vitesse-dark'))

const svg = renderMermaidSVG(diagram, colors)

The fromShikiTheme() function intelligently maps VS Code editor colors to diagram roles:

| Editor Color | Diagram Role |
|--------------|--------------|
| editor.background | bg |
| editor.foreground | fg |
| editorLineNumber.foreground | line |
| focusBorder / keyword token | accent |
| comment token | muted |
| editor.selectionBackground | surface |
| editorWidget.border | border |

---

Supported Diagrams

Flowcharts

text
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Process]
B -->|No| D[End]
C --> D

All directions supported: TD (top-down), LR (left-right), BT (bottom-top), RL (right-left).

State Diagrams

text
stateDiagram-v2
[*] --> Idle
Idle --> Processing: start
Processing --> Complete: done
Complete --> [*]

Sequence Diagrams

text
sequenceDiagram
Alice->>Bob: Hello Bob!
Bob-->>Alice: Hi Alice!
Alice->>Bob: How are you?
Bob-->>Alice: Great, thanks!

Class Diagrams

text
classDiagram
Animal <|-- Duck
Animal <|-- Fish
Animal: +int age
Animal: +String gender
Animal: +isMammal() bool
Duck: +String beakColor
Duck: +swim()
Duck: +quack()

ER Diagrams

text
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE_ITEM : contains
PRODUCT ||--o{ LINE_ITEM : "is in"

Inline Edge Styling

Use linkStyle to override edge colors and stroke widths โ€” just like Mermaid's linkStyle:

text
graph TD
A --> B --> C
linkStyle 0 stroke:#ff0000,stroke-width:2px
linkStyle default stroke:#888888

| Syntax | Effect |
| ------------------------------- | -------------------------------------- |
| linkStyle 0 stroke:#f00 | Style a single edge by index (0-based) |
| linkStyle 0,2 stroke:#f00 | Style multiple edges at once |
| linkStyle default stroke:#888 | Default style applied to all edges |

Index-specific styles override the default. Supported properties: stroke, stroke-width.

Works in both flowcharts and state diagrams.

XY Charts

Bar charts, line charts, and combinations โ€” using Mermaid's xychart-beta syntax.

Bar chart:

text
xychart-beta
title "Monthly Revenue"
x-axis [Jan, Feb, Mar, Apr, May, Jun]
y-axis "Revenue ($K)" 0 --> 500
bar [180, 250, 310, 280, 350, 420]

Line chart:

text
xychart-beta
title "User Growth"
x-axis [Jan, Feb, Mar, Apr, May, Jun]
line [1200, 1800, 2500, 3100, 3800, 4500]

Combined bar + line:

text
xychart-beta
title "Sales with Trend"
x-axis [Jan, Feb, Mar, Apr, May, Jun]
bar [300, 380, 280, 450, 350, 520]
line [300, 330, 320, 353, 352, 395]

Horizontal orientation:

text
xychart-beta horizontal
title "Language Popularity"
x-axis [Python, JavaScript, Java, Go, Rust]
bar [30, 25, 20, 12, 8]

Axis configuration:

- Categorical x-axis: x-axis [A, B, C]
- Numeric x-axis range: x-axis 0 --> 100
- Axis titles: x-axis "Category" [A, B, C]
- Y-axis range: y-axis "Score" 0 --> 100

Multi-series: Add multiple bar and/or line declarations. Each series gets a distinct color from a monochromatic palette derived from the theme's accent color.

XY Chart Styling

The chart renderer follows a clean, minimal design philosophy inspired by Apple and Craft:

- Dot grid โ€” A subtle dot pattern fills the plot area instead of traditional solid grid lines
- Rounded bars โ€” All bar corners are rounded for a modern, polished look
- Smooth curves โ€” Line series use natural cubic spline interpolation, producing mathematically smooth curves through all data points (not straight segments or staircase steps)
- Floating labels โ€” No visible axis lines or tick marks; labels float freely for a clutter-free aesthetic
- Drop-shadow lines โ€” Each line series has a subtle shadow beneath it for depth
- Monochromatic palette โ€” Series 0 uses the theme's accent color; additional series get darker/lighter shades of the same hue with subtle hue drift, adapting automatically to light or dark backgrounds
- Interactive tooltips โ€” When rendered with interactive: true, hovering over bars or data points shows value tooltips. Multi-line tooltips appear when multiple series share an x-position
- Sparse line dots โ€” Lines with 12 or fewer data points show data point dots by default for readability
- Full theme support โ€” All 15 built-in themes (and custom themes) apply to charts. The accent color drives the entire series color palette
- Live theme switching โ€” Chart series colors are CSS custom properties (--xychart-color-N), so theme changes apply instantly without re-rendering

---

ASCII Output

For terminal environments, CLI tools, or anywhere you need plain text, render to ASCII or Unicode box-drawing characters:

typescript
import { renderMermaidASCII } from 'beautiful-mermaid'

// Unicode mode (default) โ€” prettier box drawing
const unicode = renderMermaidASCII(graph LR; A --> B)

// Pure ASCII mode โ€” maximum compatibility
const ascii = renderMermaidASCII(graph LR; A --> B, { useAscii: true })

Unicode output:

text
โ”Œโ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”
โ”‚ โ”‚ โ”‚ โ”‚
โ”‚ A โ”‚โ”€โ”€โ”€โ”€โ–บโ”‚ B โ”‚
โ”‚ โ”‚ โ”‚ โ”‚
โ””โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”˜

ASCII output:

text
+---+     +---+
| | | |
| A |---->| B |
| | | |
+---+ +---+

ASCII Options

typescript
renderMermaidASCII(diagram, {
useAscii: false, // true = ASCII, false = Unicode (default)
paddingX: 5, // Horizontal spacing between nodes
paddingY: 5, // Vertical spacing between nodes
boxBorderPadding: 1, // Padding inside node boxes
colorMode: 'auto', // 'none' | 'auto' | 'ansi16' | 'ansi256' | 'truecolor' | 'html'
theme: { ... }, // Partial<AsciiTheme> โ€” override default colors
})

ASCII XY Charts

XY charts render to ASCII with dedicated chart-drawing characters:

- Bar charts โ€” โ–ˆ blocks (Unicode) or # (ASCII mode)
- Line charts โ€” Staircase routing with rounded corners: โ•ญโ•ฎโ•ฐโ•ฏโ”‚โ”€ (Unicode) or +|- (ASCII)
- Multi-series โ€” Each series gets a distinct ANSI color from the theme's accent palette
- Legends โ€” Automatically shown when multiple series are present
- Horizontal charts โ€” Fully supported with categories on the y-axis

---

API Reference

renderMermaidSVG(text, options?): string

Render a Mermaid diagram to SVG. Synchronous. Auto-detects diagram type.

Parameters:
- text โ€” Mermaid source code
- options โ€” Optional RenderOptions object

RenderOptions:

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| bg | string | #FFFFFF | Background color (or CSS variable) |
| fg | string | #27272A | Foreground color (or CSS variable) |
| line | string? | โ€” | Edge/connector color |
| accent | string? | โ€” | Arrow heads, highlights |
| muted | string? | โ€” | Secondary text, labels |
| surface | string? | โ€” | Node fill tint |
| border | string? | โ€” | Node stroke color |
| font | string | Inter | Font family |
| transparent | boolean | false | Render with transparent background |
| padding | number | 40 | Canvas padding in px |
| nodeSpacing | number | 24 | Horizontal spacing between sibling nodes |
| layerSpacing | number | 40 | Vertical spacing between layers |
| componentSpacing | number | 24 | Spacing between disconnected components |
| thoroughness | number | 3 | Crossing minimization trials (1-7, higher = better but slower) |
| interactive | boolean | false | Enable hover tooltips on XY chart bars and data points |

XY Charts: Diagrams starting with xychart-beta are auto-detected โ€” no separate function needed. The accent color option drives the chart series color palette.

renderMermaidSVGAsync(text, options?): Promise<string>

Async version of renderMermaidSVG(). Same output, returns a Promise<string>. Useful in async server handlers or data loaders.

renderMermaidASCII(text, options?): string

Render a Mermaid diagram to ASCII/Unicode text. Synchronous.

AsciiRenderOptions:

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| useAscii | boolean | false | Use ASCII instead of Unicode |
| paddingX | number | 5 | Horizontal node spacing |
| paddingY | number | 5 | Vertical node spacing |
| boxBorderPadding | number | 1 | Inner box padding |
| colorMode | string | 'auto' | 'none', 'auto', 'ansi16', 'ansi256', 'truecolor', or 'html' |
| theme | Partial<AsciiTheme> | โ€” | Override default colors for ASCII output |

parseMermaid(text): MermaidGraph

Parse Mermaid source into a structured graph object (for custom processing).

fromShikiTheme(theme): DiagramColors

Extract diagram colors from a Shiki theme object.

THEMES: Record<string, DiagramColors>

Object containing all 15 built-in themes.

DEFAULTS: { bg: string, fg: string }

Default colors (#FFFFFF / #27272A).

---

Attribution

The ASCII rendering engine is based on mermaid-ascii by Alexander Grooff. We ported it from Go to TypeScript and extended it with:

- Sequence diagram support
- Class diagram support
- ER diagram support
- Unicode box-drawing characters
- Configurable spacing and padding

Thank you Alexander for the excellent foundation!

---

License

MIT โ€” see LICENSE for details.

---

<div align="center">

Built with care by the team at Craft

</div>