lukilabs/beautiful-mermaidPublic

AI summary: A synchronous, zero-dependency renderer that turns Mermaid diagram code into styled SVGs or ASCII art instantly.

Stars
10.8K
+15 today
Forks
373
Watchers
28
Open issues
45
Open PRs
36
Contributors
~10
Commits
33
Branches
8

TypeScriptMITCreated Jan 28, 2026Last push 3mo agoLatest release v1.1.2+77 stars this week+90 this month

Star history

since Jan 25, 2026
05K10KJan 2026Mar 2026Jun 2026Aug 2026
10.8K stars as of Aug 7, 2026, tracked back to Jan 25, 2026. Historical curve reconstructed from public GitHub event archives, calibrated to the current total.

Contribution activity

commits per day, last 52 weeks
AugSepOctNovDecJanFebMarAprMayJunJulMonWedFri2025-08-02: 0 commits2025-08-03: 0 commits2025-08-04: 0 commits2025-08-05: 0 commits2025-08-06: 0 commits2025-08-07: 0 commits2025-08-08: 0 commits2025-08-09: 0 commits2025-08-10: 0 commits2025-08-11: 0 commits2025-08-12: 0 commits2025-08-13: 0 commits2025-08-14: 0 commits2025-08-15: 0 commits2025-08-16: 0 commits2025-08-17: 0 commits2025-08-18: 0 commits2025-08-19: 0 commits2025-08-20: 0 commits2025-08-21: 0 commits2025-08-22: 0 commits2025-08-23: 0 commits2025-08-24: 0 commits2025-08-25: 0 commits2025-08-26: 0 commits2025-08-27: 0 commits2025-08-28: 0 commits2025-08-29: 0 commits2025-08-30: 0 commits2025-08-31: 0 commits2025-09-01: 0 commits2025-09-02: 0 commits2025-09-03: 0 commits2025-09-04: 0 commits2025-09-05: 0 commits2025-09-06: 0 commits2025-09-07: 0 commits2025-09-08: 0 commits2025-09-09: 0 commits2025-09-10: 0 commits2025-09-11: 0 commits2025-09-12: 0 commits2025-09-13: 0 commits2025-09-14: 0 commits2025-09-15: 0 commits2025-09-16: 0 commits2025-09-17: 0 commits2025-09-18: 0 commits2025-09-19: 0 commits2025-09-20: 0 commits2025-09-21: 0 commits2025-09-22: 0 commits2025-09-23: 0 commits2025-09-24: 0 commits2025-09-25: 0 commits2025-09-26: 0 commits2025-09-27: 0 commits2025-09-28: 0 commits2025-09-29: 0 commits2025-09-30: 0 commits2025-10-01: 0 commits2025-10-02: 0 commits2025-10-03: 0 commits2025-10-04: 0 commits2025-10-05: 0 commits2025-10-06: 0 commits2025-10-07: 0 commits2025-10-08: 0 commits2025-10-09: 0 commits2025-10-10: 0 commits2025-10-11: 0 commits2025-10-12: 0 commits2025-10-13: 0 commits2025-10-14: 0 commits2025-10-15: 0 commits2025-10-16: 0 commits2025-10-17: 0 commits2025-10-18: 0 commits2025-10-19: 0 commits2025-10-20: 0 commits2025-10-21: 0 commits2025-10-22: 0 commits2025-10-23: 0 commits2025-10-24: 0 commits2025-10-25: 0 commits2025-10-26: 0 commits2025-10-27: 0 commits2025-10-28: 0 commits2025-10-29: 0 commits2025-10-30: 0 commits2025-10-31: 0 commits2025-11-01: 0 commits2025-11-02: 0 commits2025-11-03: 0 commits2025-11-04: 0 commits2025-11-05: 0 commits2025-11-06: 0 commits2025-11-07: 0 commits2025-11-09: 0 commits2025-11-10: 0 commits2025-11-11: 0 commits2025-11-12: 0 commits2025-11-13: 0 commits2025-11-14: 0 commits2025-11-15: 0 commits2025-11-16: 0 commits2025-11-17: 0 commits2025-11-18: 0 commits2025-11-19: 0 commits2025-11-20: 0 commits2025-11-21: 0 commits2025-11-22: 0 commits2025-11-23: 0 commits2025-11-24: 0 commits2025-11-25: 0 commits2025-11-26: 0 commits2025-11-27: 0 commits2025-11-28: 0 commits2025-11-29: 0 commits2025-11-30: 0 commits2025-12-01: 0 commits2025-12-02: 0 commits2025-12-03: 0 commits2025-12-04: 0 commits2025-12-05: 0 commits2025-12-06: 0 commits2025-12-07: 0 commits2025-12-08: 0 commits2025-12-09: 0 commits2025-12-10: 0 commits2025-12-11: 0 commits2025-12-12: 0 commits2025-12-13: 0 commits2025-12-14: 0 commits2025-12-15: 0 commits2025-12-16: 0 commits2025-12-17: 0 commits2025-12-18: 0 commits2025-12-19: 0 commits2025-12-20: 0 commits2025-12-21: 0 commits2025-12-22: 0 commits2025-12-23: 0 commits2025-12-24: 0 commits2025-12-25: 0 commits2025-12-26: 0 commits2025-12-27: 0 commits2025-12-28: 0 commits2025-12-29: 0 commits2025-12-30: 0 commits2025-12-31: 0 commits2026-01-01: 0 commits2026-01-02: 0 commits2026-01-03: 0 commits2026-01-04: 0 commits2026-01-05: 0 commits2026-01-06: 0 commits2026-01-07: 0 commits2026-01-08: 0 commits2026-01-09: 0 commits2026-01-10: 0 commits2026-01-11: 0 commits2026-01-12: 0 commits2026-01-13: 0 commits2026-01-14: 0 commits2026-01-15: 0 commits2026-01-16: 0 commits2026-01-17: 0 commits2026-01-18: 0 commits2026-01-19: 0 commits2026-01-20: 0 commits2026-01-21: 0 commits2026-01-22: 0 commits2026-01-23: 0 commits2026-01-24: 0 commits2026-01-25: 0 commits2026-01-26: 0 commits2026-01-27: 0 commits2026-01-28: 4 commits2026-01-29: 5 commits2026-01-30: 0 commits2026-01-31: 0 commits2026-02-01: 0 commits2026-02-02: 0 commits2026-02-03: 0 commits2026-02-04: 0 commits2026-02-05: 0 commits2026-02-06: 0 commits2026-02-07: 0 commits2026-02-08: 0 commits2026-02-09: 0 commits2026-02-10: 0 commits2026-02-11: 0 commits2026-02-12: 0 commits2026-02-13: 0 commits2026-02-14: 0 commits2026-02-15: 0 commits2026-02-16: 0 commits2026-02-17: 0 commits2026-02-18: 0 commits2026-02-19: 0 commits2026-02-20: 0 commits2026-02-21: 0 commits2026-02-22: 0 commits2026-02-23: 4 commits2026-02-24: 0 commits2026-02-25: 0 commits2026-02-26: 7 commits2026-02-27: 0 commits2026-02-28: 0 commits2026-03-01: 0 commits2026-03-02: 0 commits2026-03-03: 0 commits2026-03-04: 0 commits2026-03-05: 0 commits2026-03-06: 0 commits2026-03-07: 0 commits2026-03-08: 0 commits2026-03-09: 0 commits2026-03-10: 0 commits2026-03-11: 0 commits2026-03-12: 0 commits2026-03-13: 0 commits2026-03-14: 0 commits2026-03-15: 0 commits2026-03-16: 0 commits2026-03-17: 0 commits2026-03-18: 0 commits2026-03-19: 0 commits2026-03-20: 0 commits2026-03-21: 0 commits2026-03-22: 0 commits2026-03-23: 0 commits2026-03-24: 0 commits2026-03-25: 0 commits2026-03-26: 0 commits2026-03-27: 0 commits2026-03-28: 0 commits2026-03-29: 0 commits2026-03-30: 0 commits2026-03-31: 0 commits2026-04-01: 0 commits2026-04-02: 0 commits2026-04-03: 0 commits2026-04-04: 0 commits2026-04-05: 0 commits2026-04-06: 0 commits2026-04-07: 0 commits2026-04-08: 0 commits2026-04-09: 0 commits2026-04-10: 0 commits2026-04-11: 0 commits2026-04-12: 0 commits2026-04-13: 0 commits2026-04-14: 0 commits2026-04-15: 0 commits2026-04-16: 0 commits2026-04-17: 1 commit2026-04-18: 0 commits2026-04-19: 0 commits2026-04-20: 0 commits2026-04-21: 0 commits2026-04-22: 0 commits2026-04-23: 1 commit2026-04-24: 0 commits2026-04-25: 0 commits2026-04-26: 0 commits2026-04-27: 0 commits2026-04-28: 0 commits2026-04-29: 0 commits2026-04-30: 0 commits2026-05-01: 0 commits2026-05-02: 0 commits2026-05-03: 0 commits2026-05-04: 0 commits2026-05-05: 0 commits2026-05-06: 5 commits2026-05-07: 0 commits2026-05-08: 0 commits2026-05-09: 0 commits2026-05-10: 0 commits2026-05-11: 0 commits2026-05-12: 0 commits2026-05-13: 0 commits2026-05-14: 0 commits2026-05-15: 0 commits2026-05-16: 0 commits2026-05-17: 0 commits2026-05-18: 0 commits2026-05-19: 0 commits2026-05-20: 0 commits2026-05-21: 0 commits2026-05-22: 0 commits2026-05-23: 0 commits2026-05-24: 0 commits2026-05-25: 0 commits2026-05-26: 0 commits2026-05-27: 0 commits2026-05-28: 0 commits2026-05-29: 0 commits2026-05-30: 0 commits2026-05-31: 0 commits2026-06-01: 0 commits2026-06-02: 0 commits2026-06-03: 0 commits2026-06-04: 0 commits2026-06-05: 0 commits2026-06-06: 0 commits2026-06-07: 0 commits2026-06-08: 0 commits2026-06-09: 0 commits2026-06-10: 0 commits2026-06-11: 0 commits2026-06-12: 0 commits2026-06-13: 0 commits2026-06-14: 0 commits2026-06-15: 0 commits2026-06-16: 0 commits2026-06-17: 0 commits2026-06-18: 0 commits2026-06-19: 0 commits2026-06-20: 0 commits2026-06-21: 0 commits2026-06-22: 0 commits2026-06-23: 0 commits2026-06-24: 0 commits2026-06-25: 0 commits2026-06-26: 0 commits2026-06-27: 0 commits2026-06-28: 0 commits2026-06-29: 0 commits2026-06-30: 0 commits2026-07-01: 0 commits2026-07-02: 0 commits2026-07-03: 0 commits2026-07-04: 0 commits2026-07-05: 0 commits2026-07-06: 0 commits2026-07-07: 0 commits2026-07-08: 0 commits2026-07-09: 0 commits2026-07-10: 0 commits2026-07-11: 0 commits2026-07-12: 0 commits2026-07-13: 0 commits2026-07-14: 0 commits2026-07-15: 0 commits2026-07-16: 0 commits2026-07-17: 0 commits2026-07-18: 0 commits2026-07-19: 0 commits2026-07-20: 0 commits2026-07-21: 0 commits2026-07-22: 0 commits2026-07-23: 0 commits2026-07-24: 0 commits2026-07-25: 0 commits2026-07-26: 0 commits2026-07-27: 0 commits2026-07-28: 0 commits2026-07-29: 0 commits2026-07-30: 0 commits2026-07-31: 0 commits2026-08-01: 0 commits
27 commits in the last yearLessMore

Signals and awards

derived from tracked data
  • Widely adopted

    10,806 stars

  • Permissive license

    MIT

  • Repeat trending

    6 trending appearances

What beautiful-mermaid does

Beautiful Mermaid provides a fully synchronous rendering engine for Mermaid diagrams without relying on Puppeteer or actual browser DOM. By using a FakeWorker bypass for the ELK.js layout engine, it instantly computes SVGs directly in Node or the browser, making it ideal for React apps to avoid layout shifts. It uses an elegant two-color theming foundation that dynamically derives a full palette via CSS color-mix(), ensuring coherent visual styling. It also outputs ASCII art and integrates directly with VS Code themes via Shiki.

This library is for frontend engineers and tooling developers who need fast, reliable Mermaid diagram generation in JavaScript/TypeScript environments. It is especially useful for those tired of the asynchronous overhead and browser dependencies typical of standard Mermaid implementations.

  • Synchronous rendering: Instantly computes diagram SVGs in a single thread without promises or async/await overhead.
  • Zero DOM dependency: Runs perfectly in Node, Deno, and edge environments because it implements a FakeWorker bypass instead of a real browser.
  • Two-color theming: Derives an entire diagram color palette from just a background and foreground color using CSS color-mix().
  • CSS variable integration: Allows real-time theme switching by applying CSS variables directly to the SVG output.
  • ASCII generation: Provides an alternative text-only rendering mode suitable for terminals or code blocks.
  • Shiki compatibility: Natively imports and maps VS Code editor themes to diagram roles out-of-the-box.

Where teams use it

React and Next.js applications

Developers use it to render diagrams synchronously during server-side rendering or inside useMemo hooks to prevent loading flashes.

Documentation generation

Static site generators integrate it to turn markdown code blocks into polished SVGs at build time without needing a headless browser.

Terminal output formatting

CLI tools utilize the ASCII rendering mode to visually display complex graphs or execution trees directly in the console.

Dynamic theming engines

Web apps that implement light/dark modes pass CSS variables to the renderer so diagrams update instantly without being redrawn.

Getting started: npm install beautiful-mermaid

README

main branch

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 License

Live Demo & Samples

→ Use it live in Craft Agents


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

npm install beautiful-mermaid
# or
bun add beautiful-mermaid
# or
pnpm add beautiful-mermaid

Quick Start

SVG Output

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

import { renderMermaidASCII } from 'beautiful-mermaid'

const ascii = renderMermaidASCII(`graph LR; A --> B --> C`)
┌───┐     ┌───┐     ┌───┐
│   │     │   │     │   │
│ A │────►│ B │────►│ C │
│   │     │   │     │   │
└───┘     └───┘     └───┘

React Integration

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

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():

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:

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:

// 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:

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
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:

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

const svg = renderMermaidSVG(diagram, myTheme)

Want richer colors? Add any of the optional enrichments:

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:

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

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

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

Sequence Diagrams

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

Class Diagrams

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

ER Diagrams

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:

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:

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:

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

Combined bar + line:

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:

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:

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:

┌───┐     ┌───┐
│   │     │   │
│ A │────►│ B │
│   │     │   │
└───┘     └───┘

ASCII output:

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

ASCII Options

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.


Built with care by the team at Craft

View on GitHub

Recent activity

commits and pull requests

Releases and announcements

6 total
  1. v1.1.2v1.1.2Feb 26, 2026

    Ship pre-built JavaScript for webpack/vite/Node consumers. ### What changed - **Dual exports** — Bun gets raw `.ts` (zero overhead), Node/webpack/vite get pre-built ESM from `dist/` - **No config needed** — conditional exports in `package.json` handle routing automatically - **tsup build** — ESM + declaration files + source maps ### Fixes - Closes #45 — package no longer breaks webpack consumers that don't transpile `node_modules` ### Full Changelog https://github.com/lukilabs/beautiful-mermaid/compare/v1.1.1...v1.1.2

  2. v1.1.0v1.1.0Feb 26, 2026

    ## What's New ### XY Charts (bar, line, combined) Full support for Mermaid's `xychart-beta` syntax — bar charts, line charts, and combinations with: - Multi-series with monochromatic color palette derived from theme accent - Smooth cubic spline interpolation for line series - Interactive tooltips (hover bars/data points) - Horizontal orientation support - Dot grid background, rounded bars, floating labels - ASCII/Unicode rendering for terminal output - Full theme support with live CSS variable switching ### Inline Edge Styling (`linkStyle`) Style individual edges by index or set defaults — `stroke`, `stroke-width` supported. Works in flowcharts and state diagrams. ### CJK State Diagram Support State diagrams now correctly parse Chinese, Japanese, Korean and other Unicode characters in state names, transitions, and descriptions. ### Text-Embedded Edge Labels Flowcharts now support text-embedded label syntax (`-- Yes -->`, `-. Maybe .->`, `== Sure ==>`) as an alternative to pipe syntax (`-->|Yes|`). *Thanks to [@liuxiaopai-ai](https://github.com/liuxiaopai-ai) for the original branch label implementation in #36.* ## Full Changelog - feat: XY Charts — bar, line, combined, horizo

  3. v1.0.2v1.0.2Feb 23, 2026

    ### Changes - Remove `DOM` lib from tsconfig — use ambient `declare const` for browser globals (`document`, `window`) - This avoids pulling in the entire DOM type namespace for a library with zero DOM dependencies

  4. v1.0.1v1.0.1Feb 23, 2026

    ## Layout Quality Improvements - **Centering**: `contentAlignment H_CENTER V_CENTER` for subgraphs - **Node placement**: BALANCED fixed alignment at root and subgraph level - **Edge spacing**: optimized edgeEdge, edgeEdgeBetweenLayers, edgeNodeBetweenLayers - **High-degree nodes**: special treatment for nodes with 8+ connections - **Post-compaction**: LEFT_RIGHT_CONSTRAINT_LOCKING at root level - **Model order**: NODES_AND_EDGES preservation at root level ## Layer Alignment Post-processing step that snaps same-layer nodes to uniform flow-axis positions, fixing the visual stagger caused by ELK's orthogonal edge routing. Uses single-linkage clustering for accurate grouping across any fan-out size. ## Edge Bundling Fan-out/fan-in edges now share common trunk segments with subgraph-aware junction placement. ## Bug Fixes - Fix edit dialog SVG rendering, source panel update, and close timing - Workarounds for ELK 0.11.0 compound node bugs ([eclipse-elk/elk#724](https://github.com/eclipse-elk/elk/issues/724))

  5. v1.0.0v1.0.0Feb 23, 2026137 downloads

    ## beautiful-mermaid v1.0.0 ### Layout Engine - **ELK.js replaces dagre** — fully synchronous layout via FakeWorker bypass, better edge routing and subgraph handling - **Shape-aware edge clipping** — edges terminate at actual shape boundaries (e.g. diamond vertices), not bounding boxes - **New layout options** — `nodeSpacing`, `layerSpacing`, `componentSpacing`, `thoroughness` for fine-grained control - **Disconnected component support** — graphs with unconnected subgraphs now lay out properly - **Per-subgraph direction overrides** — nested subgraphs can have independent LR/TD/BT/RL direction ### Multi-line Labels & Formatting - **`<br>` tags** in node labels, edge labels, and subgraph headers — line breaks work everywhere - **Inline formatting** — `<b>`, `<i>`, `<u>`, `<s>` tags render as bold/italic/underline/strikethrough in SVG - **Variable-width text measurement** — character-class buckets (narrow, wide, CJK, emoji) instead of fixed-ratio estimation ### Themeable ASCII - **ANSI color modes** — `none`, `ansi16`, `ansi256`, `truecolor`, and `html` (for browser rendering) - **`AsciiTheme` type** — customize colors per role: `fg`, `border`, `line`, `arrow`, `corner`, `junction`

Code frequency

additions and deletions
+20.4K-20.4KWeek of 2026-01-25: +20,042 linesWeek of 2026-01-25: -39 linesWeek of 2026-02-01: +0 linesWeek of 2026-02-01: -0 linesWeek of 2026-02-08: +0 linesWeek of 2026-02-08: -0 linesWeek of 2026-02-15: +0 linesWeek of 2026-02-15: -0 linesWeek of 2026-02-22: +20,357 linesWeek of 2026-02-22: -3,449 linesWeek of 2026-03-01: +0 linesWeek of 2026-03-01: -0 linesWeek of 2026-03-08: +0 linesWeek of 2026-03-08: -0 linesWeek of 2026-03-15: +0 linesWeek of 2026-03-15: -0 linesWeek of 2026-03-22: +0 linesWeek of 2026-03-22: -0 linesWeek of 2026-03-29: +0 linesWeek of 2026-03-29: -0 linesWeek of 2026-04-05: +0 linesWeek of 2026-04-05: -0 linesWeek of 2026-04-12: +2,797 linesWeek of 2026-04-12: -41 linesWeek of 2026-04-19: +1,010 linesWeek of 2026-04-19: -697 linesWeek of 2026-04-26: +0 linesWeek of 2026-04-26: -0 linesWeek of 2026-05-03: +29 linesWeek of 2026-05-03: -5 linesWeek of 2026-05-10: +0 linesWeek of 2026-05-10: -0 linesWeek of 2026-05-17: +0 linesWeek of 2026-05-17: -0 linesWeek of 2026-05-24: +0 linesWeek of 2026-05-24: -0 linesWeek of 2026-05-31: +0 linesWeek of 2026-05-31: -0 linesWeek of 2026-06-07: +0 linesWeek of 2026-06-07: -0 linesWeek of 2026-06-14: +0 linesWeek of 2026-06-14: -0 linesWeek of 2026-06-21: +0 linesWeek of 2026-06-21: -0 linesWeek of 2026-06-28: +0 linesWeek of 2026-06-28: -0 linesWeek of 2026-07-05: +0 linesWeek of 2026-07-05: -0 linesWeek of 2026-07-12: +0 linesWeek of 2026-07-12: -0 linesWeek of 2026-07-19: +0 linesWeek of 2026-07-19: -0 linesWeek of 2026-07-26: +0 linesWeek of 2026-07-26: -0 linesJan 25, 2026Jul 26, 2026
+44.2K lines added, -4.2K removed over the last year.

Commits per week

last 52 weeks
110Week of 2025-08-02: 0 commitsWeek of 2025-08-09: 0 commitsWeek of 2025-08-16: 0 commitsWeek of 2025-08-23: 0 commitsWeek of 2025-08-30: 0 commitsWeek of 2025-09-06: 0 commitsWeek of 2025-09-13: 0 commitsWeek of 2025-09-20: 0 commitsWeek of 2025-09-27: 0 commitsWeek of 2025-10-04: 0 commitsWeek of 2025-10-11: 0 commitsWeek of 2025-10-18: 0 commitsWeek of 2025-10-25: 0 commitsWeek of 2025-11-01: 0 commitsWeek of 2025-11-09: 0 commitsWeek of 2025-11-16: 0 commitsWeek of 2025-11-23: 0 commitsWeek of 2025-11-30: 0 commitsWeek of 2025-12-07: 0 commitsWeek of 2025-12-14: 0 commitsWeek of 2025-12-21: 0 commitsWeek of 2025-12-28: 0 commitsWeek of 2026-01-04: 0 commitsWeek of 2026-01-11: 0 commitsWeek of 2026-01-18: 0 commitsWeek of 2026-01-25: 9 commitsWeek of 2026-02-01: 0 commitsWeek of 2026-02-08: 0 commitsWeek of 2026-02-15: 0 commitsWeek of 2026-02-22: 11 commitsWeek of 2026-03-01: 0 commitsWeek of 2026-03-08: 0 commitsWeek of 2026-03-15: 0 commitsWeek of 2026-03-22: 0 commitsWeek of 2026-03-29: 0 commitsWeek of 2026-04-05: 0 commitsWeek of 2026-04-12: 1 commitsWeek of 2026-04-19: 1 commitsWeek of 2026-04-26: 0 commitsWeek of 2026-05-03: 5 commitsWeek of 2026-05-10: 0 commitsWeek of 2026-05-17: 0 commitsWeek of 2026-05-24: 0 commitsWeek of 2026-05-31: 0 commitsWeek of 2026-06-07: 0 commitsWeek of 2026-06-14: 0 commitsWeek of 2026-06-21: 0 commitsWeek of 2026-06-28: 0 commitsWeek of 2026-07-05: 0 commitsWeek of 2026-07-12: 0 commitsWeek of 2026-07-19: 0 commitsWeek of 2026-07-26: 0 commitsAug 2, 2025Jul 26, 2026
27 commits in the last 52 weeks.

When work happens

weekday and hour
SunMonTueWedThuFriSat036912151821Sun 0:00 — 0 commitsSun 1:00 — 0 commitsSun 2:00 — 0 commitsSun 3:00 — 0 commitsSun 4:00 — 0 commitsSun 5:00 — 0 commitsSun 6:00 — 0 commitsSun 7:00 — 0 commitsSun 8:00 — 0 commitsSun 9:00 — 0 commitsSun 10:00 — 0 commitsSun 11:00 — 0 commitsSun 12:00 — 0 commitsSun 13:00 — 0 commitsSun 14:00 — 0 commitsSun 15:00 — 0 commitsSun 16:00 — 0 commitsSun 17:00 — 0 commitsSun 18:00 — 0 commitsSun 19:00 — 0 commitsSun 20:00 — 0 commitsSun 21:00 — 0 commitsSun 22:00 — 0 commitsSun 23:00 — 0 commitsMon 0:00 — 0 commitsMon 1:00 — 0 commitsMon 2:00 — 0 commitsMon 3:00 — 0 commitsMon 4:00 — 0 commitsMon 5:00 — 0 commitsMon 6:00 — 0 commitsMon 7:00 — 0 commitsMon 8:00 — 0 commitsMon 9:00 — 0 commitsMon 10:00 — 0 commitsMon 11:00 — 0 commitsMon 12:00 — 1 commitsMon 13:00 — 0 commitsMon 14:00 — 0 commitsMon 15:00 — 0 commitsMon 16:00 — 0 commitsMon 17:00 — 1 commitsMon 18:00 — 2 commitsMon 19:00 — 0 commitsMon 20:00 — 0 commitsMon 21:00 — 0 commitsMon 22:00 — 0 commitsMon 23:00 — 0 commitsTue 0:00 — 0 commitsTue 1:00 — 0 commitsTue 2:00 — 0 commitsTue 3:00 — 0 commitsTue 4:00 — 0 commitsTue 5:00 — 0 commitsTue 6:00 — 0 commitsTue 7:00 — 0 commitsTue 8:00 — 0 commitsTue 9:00 — 0 commitsTue 10:00 — 0 commitsTue 11:00 — 0 commitsTue 12:00 — 0 commitsTue 13:00 — 0 commitsTue 14:00 — 0 commitsTue 15:00 — 0 commitsTue 16:00 — 0 commitsTue 17:00 — 0 commitsTue 18:00 — 0 commitsTue 19:00 — 0 commitsTue 20:00 — 0 commitsTue 21:00 — 0 commitsTue 22:00 — 0 commitsTue 23:00 — 0 commitsWed 0:00 — 0 commitsWed 1:00 — 0 commitsWed 2:00 — 0 commitsWed 3:00 — 0 commitsWed 4:00 — 0 commitsWed 5:00 — 0 commitsWed 6:00 — 0 commitsWed 7:00 — 0 commitsWed 8:00 — 0 commitsWed 9:00 — 1 commitsWed 10:00 — 0 commitsWed 11:00 — 0 commitsWed 12:00 — 4 commitsWed 13:00 — 0 commitsWed 14:00 — 0 commitsWed 15:00 — 0 commitsWed 16:00 — 0 commitsWed 17:00 — 4 commitsWed 18:00 — 0 commitsWed 19:00 — 0 commitsWed 20:00 — 0 commitsWed 21:00 — 0 commitsWed 22:00 — 0 commitsWed 23:00 — 0 commitsThu 0:00 — 0 commitsThu 1:00 — 0 commitsThu 2:00 — 0 commitsThu 3:00 — 0 commitsThu 4:00 — 0 commitsThu 5:00 — 0 commitsThu 6:00 — 0 commitsThu 7:00 — 0 commitsThu 8:00 — 0 commitsThu 9:00 — 0 commitsThu 10:00 — 0 commitsThu 11:00 — 0 commitsThu 12:00 — 0 commitsThu 13:00 — 1 commitsThu 14:00 — 6 commitsThu 15:00 — 2 commitsThu 16:00 — 0 commitsThu 17:00 — 0 commitsThu 18:00 — 0 commitsThu 19:00 — 2 commitsThu 20:00 — 1 commitsThu 21:00 — 1 commitsThu 22:00 — 0 commitsThu 23:00 — 0 commitsFri 0:00 — 0 commitsFri 1:00 — 0 commitsFri 2:00 — 0 commitsFri 3:00 — 0 commitsFri 4:00 — 0 commitsFri 5:00 — 0 commitsFri 6:00 — 0 commitsFri 7:00 — 0 commitsFri 8:00 — 0 commitsFri 9:00 — 0 commitsFri 10:00 — 0 commitsFri 11:00 — 0 commitsFri 12:00 — 0 commitsFri 13:00 — 0 commitsFri 14:00 — 0 commitsFri 15:00 — 1 commitsFri 16:00 — 0 commitsFri 17:00 — 0 commitsFri 18:00 — 0 commitsFri 19:00 — 0 commitsFri 20:00 — 0 commitsFri 21:00 — 0 commitsFri 22:00 — 0 commitsFri 23:00 — 0 commitsSat 0:00 — 0 commitsSat 1:00 — 0 commitsSat 2:00 — 0 commitsSat 3:00 — 0 commitsSat 4:00 — 0 commitsSat 5:00 — 0 commitsSat 6:00 — 0 commitsSat 7:00 — 0 commitsSat 8:00 — 0 commitsSat 9:00 — 0 commitsSat 10:00 — 0 commitsSat 11:00 — 0 commitsSat 12:00 — 0 commitsSat 13:00 — 0 commitsSat 14:00 — 0 commitsSat 15:00 — 0 commitsSat 16:00 — 0 commitsSat 17:00 — 0 commitsSat 18:00 — 0 commitsSat 19:00 — 0 commitsSat 20:00 — 0 commitsSat 21:00 — 0 commitsSat 22:00 — 0 commitsSat 23:00 — 0 commits
Commit volume by weekday and hour (UTC). Larger dots mean more commits.
DateListRankStars gained
Feb 6, 2026daily#15+194
Feb 2, 2026daily#21+124
Feb 1, 2026daily#14+183
Jan 31, 2026daily#5+325
Jan 30, 2026daily#4+507
Jan 29, 2026daily#2+638
  • freeCodeCamp/freeCodeCamp

    freeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.

    453.6K stars · TypeScript

  • openclaw/openclaw

    Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞

    385.5K stars · TypeScript

  • openclaw/openclaw

    Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞

    384.4K stars · TypeScript

  • openclaw/openclaw

    Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞

    384.4K stars · TypeScript

  • openclaw/openclaw

    Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞

    384.4K stars · TypeScript

  • anomalyco/opencode

    The open source coding agent.

    194.7K stars · TypeScript