npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vercel/beautiful-mermaid

v0.1.5

Published

Render Mermaid diagrams as beautiful SVGs or ASCII art. Ultra-fast, fully themeable, zero DOM dependencies.

Maintainers

sebastianromingsebastianromingcraigandrewscraigandrewsgkaragkiaourisgkaragkiaourisdglsparsonsdglsparsonsbvred4244bvred4244dummdidummdummdidummadriancooney_verceladriancooney_verceleveporcelloeveporcellobcorn-celybcorn-celyatinuxatinuxdvoytenkodvoytenkoamyeganamyeganbrookemosbybrookemosbyfeugyfeugyswarnavasenguptaswarnavasenguptaraunofreibergraunofreibergmamusomamusogoncygoncysmaeda-kssmaeda-kshenryheffernanhenryheffernangargis5gargis5wycatswycatsyvonnezhouyvonnezhouchibicodechibicodeandybitzandybitziamevilrabbitiamevilrabbittootallnatetootallnatestyflestyflematthewbinshtokmatthewbinshtokmglagolamglagolajavivelascojavivelascoluimeyluimeytimertimerlucleraylucleraymatheussmatheussanatrajkovskaanatrajkovskan0rlant1sn0rlant1sjooliashijooliashitimneutkenstimneutkenselsighelsighwitswitslpalmeslpalmescl3arglasscl3arglasssamsislesamsislechriswdmrchriswdmrrizbizkitsrizbizkitsismaelrumzanismaelrumzanrich.davis.vercelrich.davis.vercelcreationixcreationixfeedthejimfeedthejimcasey.gowriecasey.gowrierauchgrauchghuozhihuozhialdoschaldoschlfadeslfadesokbelokbeljerilynzjerilynzhedyzandihedyzandipadmaiapadmaiadelbadelbasokrasokragsandhugsandhudbredvickdbredvickhungrybearstudiohungrybearstudiocalebboydcalebboydhellojennifertranhellojennifertranmarcgreenstockmarcgreenstockagadzikagadziktknickmantknickmanjanoryjanoryjeffreyarnesonjeffreyarnesonmattjaredmattjaredmsimulcikmsimulcikgdbortongdbortoncorrettojscorrettojscramforcecramforcekakadiadarpankakadiadarpanmaxleitermaxleiterkit-fosterkit-fostertilly3gtilly3gecklfecklfhealeycodeshealeycodesdferber90dferber90epallerolsepallerolsnicolas-webdevnicolas-webdevschlezschleznpm_bot_vercel_supportnpm_bot_vercel_supportpieparkerpieparkerjtaylor0196jtaylor0196javierbytejavierbyteemeraldsantoemeraldsantogaspar09gaspar09mmastracmmastracsr_internsr_interngudmundurgudmundurnick.traceynick.traceybmealeybmealeydoquedoqueaaorrisaaorrisnutanutadaniel.campbelldaniel.campbellquiibzquiibzchloe.tedderchloe.teddermjakobismjakobismehulkarmehulkartcc-sejohnsontcc-sejohnsonfiliphassonfiliphassonlubakravchelubakravchegnoffgnoffmatt.strakamatt.strakawbinnssmithwbinnssmithofhouseofhousemknichel-vercelmknichel-vercelvvovvovercel-release-botvercel-release-botrob-peters-vercelrob-peters-vercelgt-codesgt-codesbalazsorbanbalazsorbantobiaslinstobiaslinstiago-loureirotiago-loureirombrakkenmbrakkentimolinstimolinsanthonyshewanthonyshewcmeyer_vercelcmeyer_vercelmiguelalcaldemiguelalcaldelaugharnlaugharnviekoviekorobin-vercelrobin-vercelwude935wude935zach-baldazach-baldaah100101ah100101quietshuquietshuijjkijjkvercelbenvercelbenzharichzharichjoey.berkowitzjoey.berkowitzdfeindfeinonsclomonsclomashok.gurumurthyashok.gurumurthydavidverceldavidverceldiscepolidiscepoliowoceowoceergun1017ergun1017shaper42shaper42ademauademaulayonthebeechlayonthebeechjeffsee55jeffsee55zeejabzeejabacdliteacdlitemcabs3mcabs3msemperemsemperekldavis4kldavis4lukahartwiglukahartwigbgwbgwmikevercelmikevercelsipexsipexjeremyphilemonjeremyphilemoneprosimoneprosimonrithmicrithmicdanmfoxdanmfoxn-vigiern-vigiervercelmattvercelmattjudegaojudegaovercel-ctatevercel-ctatesjoedwardssjoedwardsalbanesealbanesesceilersceilerlgrammellgrammeljamesvclementsjamesvclementstomocchinotomocchinoaryamankhaaryamankhatechwraithtechwraithmattfroggettmattfroggetteps1loneps1lonpbzonapbzonamalewis5malewis5devjiwonchoidevjiwonchoitwwrighttwwrightwilson-w-vercelwilson-w-vercelkonstvkonstvzacktannerzacktannergabenunezgabenunezshadcnshadcnunstubbableunstubbablemario.lopez.arturomario.lopez.arturosueplexsueplexethansheaethansheaidoatvercelidoatvercelwentsulwentsulvikhyathvikhyathmischnicmischnichgstrmhgstrmdcampvc01dcampvc01mitul-smitul-sjonpheyjonpheyannagzhannagzhrich_harrisrich_harrisandrewbarbaandrewbarbabcjrobertsbcjrobertsmarc-vercelmarc-vercelali-vercelali-vercelduijfduijfplmrryplmrrytmdotmdojulianbenegasjulianbenegasrao.chandanrao.chandanthebigsadowskithebigsadowskigovind-vercelgovind-verceltomjohndesigntomjohndesignbshanzbshanzaubreychamberlainaubreychamberlainkmiddleton14kmiddleton14yavoryavorgracelliugracelliu1st11st1whatplanwhatplanfmoorfmoorvercel-eddievercel-eddietristantcoopertristantcooperrklaeserrklaesermerycodesmerycodesnmelmsnmelmsyasoobr0yasoobr0m7rcelom7rceloestebansuarezestebansuarezbobmshannonbobmshannoncaseyokeefecaseyokeefebhrigubhrigulaksshhlaksshhzackelanzackelankelzceanakelzceanahannah.hearthhannah.hearthfalcoagustin.vercelfalcoagustin.vercelnpasquinzonpasquinzokobologkobologtimwhite96timwhite96jnsahajjnsahajastephen100astephen100sylviezhangsylviezhangmatiasgfmatiasgflukesheardlukesheardadrientheboadrienthebokarthiklangtracekarthiklangtraceelpranselpransrihanarfanrihanarfanolivercarmontolivercarmontjjdopkinjjdopkinvercel_it_service_accountvercel_it_service_accountadamdongadamdongrhyssullivanrhyssullivanvalerian-rochevalerian-rocheallen-vercelallen-vercelalli-vercelalli-vercelethsheaethsheascotttrinhscotttrinhjaclarkejaclarkebkonklebkonkleseverinlandoltseverinlandoltkevinjosethomaskevinjosethomasjaygengelbachjaygengelbachchriskindlchriskindltk04tk04gschogschokavinvallikavinvallinsidnevnsidnevyash-kothari-vercelyash-kothari-vercelrobherleyrobherleymingchungxmingchungxmbaizambaizabenyebaibenyebaitimothyjordantimothyjordantristano45tristano45andyw22andyw22shagrawalshagrawalneil-vercelneil-vercelskullfaceskullfacefernandorojofernandorojokevin.corbettkevin.corbettzacowanzacowanjoelhooksjoelhookswillvileswillvilesmarkandrusmarkandrusloganliffickloganliffickyoungbloodcybyoungbloodcybkapehe_okkapehe_okhaydenbleaselhaydenbleaselquuuquuujteesangjteesangpckirklandpckirklanddavid_keefedavid_keefejeffreypojeffreypoaormi-vercelaormi-verceldarafshehdarafshehmarkpython86markpython86lazarvlazarvtonypantonypanjackjacksonverceljackjacksonvercelseif.ghezalaseif.ghezalamiksumiksuwillsatherwillsatheramanazadamanazadjacobparisjacobparisicyjosephicyjosephvercelliotvercelliotlukesandberglukesandbergnicolasmontonenicolasmontonevoodootikigodvoodootikigodjustinkroppjustinkroppsatya-callstacksatya-callstackchristianhubbardchristianhubbardwoshuajolkwoshuajolkbennorbennorstranglestranglebmishkinbmishkinmshepaneshmshepaneshkarimhaseboukarimhasebouwilliamboutwilliamboutpranaygppranaygpalex-groveralex-groverchrmcd-verchrmcd-verallenzhou101allenzhou101dmoridmoriiansbrashiansbrashalice-wonderedalice-wonderedmatchaimatchaivishalyathishvishalyathishsamselikoffsamselikoffmrsasuu_ckmrsasuu_ckmtoth-vercelmtoth-vercelanshuman71anshuman71runewolf7runewolf7rohantaneja-vercelrohantaneja-vercelhp_arorahp_arorajoyboy-0joyboy-0matiasperzmatiasperzjverceljverceltannerverceltannervercelgi_wrightygi_wrightymatthewstanciumatthewstanciurickeymcgregorrickeymcgregorrichardkunklirichardkunklibwalvoordbwalvoordrobpruzanrobpruzandanielroedanielroerahuliyer-vercelrahuliyer-vercelty37zhangty37zhangshawnfeldmanshawnfeldmanjohnphamousjohnphamous6ary6aryricardo-agzricardo-agzaej11aaej11amclenhardmclenhardreynaldo-vercelreynaldo-verceljaredthompson22jaredthompson22jetthenjetthenrobkebabrobkebabraidaltraidaltcodyellowcodyellowpablostanleypablostanleyronnie-hanifronnie-hanifzypxzypxtheclethecleandy.rianchoandy.rianchojonasherrjonasherrvanessaxteovanessaxteotomdaletomdalevincent-derksvincent-derksgrappeggiagrappeggiavaguelyseriousvaguelyseriousmkrrmkrrdalyd14dalyd14kaciebkaciebgr2mgr2mkarim_v1karim_v1simhskalsimhskal

Readme

beautiful-mermaid

Render Mermaid diagrams as beautiful SVGs or ASCII art

Ultra-fast, fully themeable, animated, 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


Features

  • 5 diagram types — Flowcharts, State, Sequence, Class, and ER diagrams
  • Dual output — SVG for rich UIs, ASCII/Unicode for terminals
  • 17 built-in themes — Including Vercel dark/light, and dead simple to add your own
  • Rank-by-rank animation — Nodes fade in, edges draw in with traveling arrows, CSS + SMIL
  • 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

Quick Start

SVG Output

import { renderMermaid } from 'beautiful-mermaid'

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

With Animation

const svg = await renderMermaid(diagram, {
  animate: true,  // rank-by-rank animation with sane defaults
})

// Or customize:
const svg = await renderMermaid(diagram, {
  animate: {
    duration: 650,
    stagger: 0,
    nodeOverlap: 0.35,
    nodeAnimation: 'fade-up',
  },
})

ASCII Output

import { renderMermaidAscii } from 'beautiful-mermaid'

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

Browser (Script Tag)

<script src="https://unpkg.com/beautiful-mermaid/dist/beautiful-mermaid.browser.global.js"></script>
<script>
  const { renderMermaid, THEMES } = beautifulMermaid;
  renderMermaid('graph TD; A-->B', { ...THEMES['vercel-dark'], animate: true })
    .then(svg => { ... });
</script>

Theming

The Two-Color Foundation

Every diagram needs just two colors: background (bg) and foreground (fg):

const svg = await renderMermaid(diagram, {
  bg: '#1a1b26',
  fg: '#a9b1d6',
})

Everything else is derived via color-mix().

Enriched Mode

Override specific derived colors:

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

Built-in Themes

17 themes ship out of the box:

import { renderMermaid, THEMES } from 'beautiful-mermaid'

const svg = await renderMermaid(diagram, THEMES['vercel-dark'])

| Theme | Type | Background | |-------|------|------------| | vercel-dark | Dark | #0A0A0A | | vercel-light | Light | #FFFFFF | | tokyo-night | Dark | #1a1b26 | | tokyo-night-storm | Dark | #24283b | | tokyo-night-light | Light | #d5d6db | | catppuccin-mocha | Dark | #1e1e2e | | catppuccin-latte | Light | #eff1f5 | | nord | Dark | #2e3440 | | nord-light | Light | #eceff4 | | dracula | Dark | #282a36 | | github-light | Light | #ffffff | | github-dark | Dark | #0d1117 | | solarized-light | Light | #fdf6e3 | | solarized-dark | Dark | #002b36 | | one-dark | Dark | #282c34 | | zinc-dark | Dark | #18181B |

Default theme (when no colors provided) is Vercel dark (#0A0A0A / #EDEDED).

Shiki Compatibility

Use any VS Code theme via Shiki:

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

const hl = await getSingletonHighlighter({ themes: ['vitesse-dark'] })
const colors = fromShikiTheme(hl.getTheme('vitesse-dark'))
const svg = await renderMermaid(diagram, colors)

Animation

Pass animate: true for rank-by-rank animation with sane defaults, or customize with AnimationOptions.

How It Works

  • Nodes fade in rank-by-rank (top → bottom)
  • Edges draw in via stroke-dashoffset with pathLength="1"
  • Arrow tips travel along the path via SMIL <animateMotion>, synced with edge easing
  • Subgroups fade in after their contents are mostly visible
  • Cascade: source node → edge draws → target node appears (with configurable overlap)

All CSS-based (works in standalone SVG files, no JS runtime needed). SMIL used only for arrow travel.

AnimationOptions

interface AnimationOptions {
  duration?: number        // Each element's animation duration (ms). Default: 650
  stagger?: number         // Delay between consecutive elements (ms). Default: 0
  nodeOverlap?: number     // How early node appears before incoming edge finishes
                           // (0 = wait, 0.5 = halfway, 1 = with edge). Default: 0.35
  groupDelay?: number      // Extra offset for group container (ms). Default: 110
  nodeEasing?: string      // CSS easing for nodes/groups. Default: 'ease'
  edgeEasing?: string      // CSS easing for edge draw-in + arrow travel. Default: 'ease-in-out'
  nodeAnimation?: string   // 'fade' | 'fade-up' | 'scale' | 'none'. Default: 'fade'
  edgeAnimation?: string   // 'draw' | 'fade' | 'none'. Default: 'draw'
  reducedMotion?: boolean  // Respect prefers-reduced-motion. Default: true
}

Easing Design

| Element | Easing | Rationale | |---------|--------|-----------| | Nodes/groups | nodeEasing | Elements "appear" — deceleration curve | | Edge lines | edgeEasing | Lines "flow" — acceleration/deceleration | | Arrow tips | auto-derived from edgeEasing | SMIL keySplines converted from CSS cubic-bezier, guaranteed sync | | Edge labels | nodeEasing | Labels are content, not motion |

Accessibility

When reducedMotion: true (default), a @media (prefers-reduced-motion: reduce) block disables all animations, showing the diagram instantly.


Layout & Styling Options

RenderOptions

| Option | Type | Default | Description | |--------|------|---------|-------------| | bg | string | #0A0A0A | Background color | | fg | string | #EDEDED | Foreground color | | 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 | Geist | Font family | | fontSize | number | 19.2 | Node label font size (px) | | fontWeight | number | 400 | Node label font weight | | letterSpacing | number | -0.384 | Node label letter spacing (px) | | edgeFontSize | number | 10 | Edge label font size (px) | | nodePaddingX | number | 24 | Horizontal padding inside nodes (px) | | nodePaddingY | number | 24 | Vertical padding inside nodes (px) | | cornerRadius | number | 6 | Node corner radius (px) | | lineWidth | number | 1.5 | Edge stroke width (px) | | edgeBendRadius | number | 8 | Rounded corners on edge bends (px) | | padding | number | 80 | Canvas padding (px) | | nodeSpacing | number | 40 | Horizontal spacing between nodes (px) | | layerSpacing | number | 50 | Vertical spacing between layers (px) | | transparent | boolean | false | Transparent background | | animate | boolean \| AnimationOptions | false | Enable animation |

Subgraph Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | groupFont | string | Geist Mono | Subgraph header font family | | groupFontSize | number | 16 | Subgraph header font size (px) | | groupFontWeight | number | 600 | Subgraph header font weight | | groupTextTransform | string | uppercase | Subgraph header text transform | | groupCornerRadius | number | 3 | Subgraph corner radius (px) | | groupBorderColor | string | #454545 | Subgraph border color | | groupPaddingX | number | 32 | Subgraph horizontal padding (px) | | groupPaddingY | number | 32 | Subgraph vertical padding (px) |

Subgraph backgrounds use a diagonal hatching pattern.


Supported Diagrams

Flowcharts

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

All directions: TD, LR, BT, RL. Subgraphs supported.

State Diagrams

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

Sequence Diagrams

sequenceDiagram
  Alice->>Bob: Hello Bob!
  Bob-->>Alice: Hi Alice!

Class Diagrams

classDiagram
  Animal <|-- Duck
  Animal: +int age
  Duck: +swim()

ER Diagrams

erDiagram
  CUSTOMER ||--o{ ORDER : places
  ORDER ||--|{ LINE_ITEM : contains

ASCII Output

import { renderMermaidAscii } from 'beautiful-mermaid'

const unicode = renderMermaidAscii(`graph LR; A --> B`)
const ascii = renderMermaidAscii(`graph LR; A --> B`, { useAscii: true })

| Option | Type | Default | Description | |--------|------|---------|-------------| | useAscii | boolean | false | ASCII instead of Unicode | | paddingX | number | 5 | Horizontal node spacing | | paddingY | number | 5 | Vertical node spacing | | boxBorderPadding | number | 1 | Inner box padding |


Attribution

ASCII rendering based on mermaid-ascii by Alexander Grooff (ported from Go, extended with sequence/class/ER support).

License

MIT — see LICENSE for details.


Built with care by the team at Craft