<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Levi Liu</title>
    <description>The latest articles on DEV Community by Levi Liu (@levi_liu).</description>
    <link>https://dev.to/levi_liu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3923265%2Ffe4d37ec-b536-47ca-961f-52b899ecf158.png</url>
      <title>DEV Community: Levi Liu</title>
      <link>https://dev.to/levi_liu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/levi_liu"/>
    <language>en</language>
    <item>
      <title>Adding Beautiful Diagrams to Your Docusaurus / VitePress Site</title>
      <dc:creator>Levi Liu</dc:creator>
      <pubDate>Sat, 11 Jul 2026 09:21:45 +0000</pubDate>
      <link>https://dev.to/levi_liu/adding-beautiful-diagrams-to-your-docusaurus-vitepress-site-8fh</link>
      <guid>https://dev.to/levi_liu/adding-beautiful-diagrams-to-your-docusaurus-vitepress-site-8fh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
Docusaurus and VitePress both render Mermaid, but the defaults ship the same washed-out pastel diagrams as everyone else's docs. The 10-minute fix is enabling the built-in Mermaid support; the 30-minute fix is picking a theme once at the renderer instead of pasting &lt;code&gt;%%{init}%%&lt;/code&gt; into every block. This post walks both — plugin install, theme config, and the moment it's worth swapping the renderer entirely for a hosted embed URL.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The doc site tax on Mermaid diagrams
&lt;/h2&gt;

&lt;p&gt;You picked Docusaurus or VitePress because you wanted a doc site that looked considered. Sans-serif that isn't Times New Roman. A sidebar that respects your section hierarchy. Code blocks with a syntax highlighter that isn't from 2012.&lt;/p&gt;

&lt;p&gt;Then you dropped in your first Mermaid diagram and the doc suddenly looked like every other Mermaid-in-docs page on the internet. Pale blue nodes on white. Thin grey edges. A font that doesn't match anything else on the page. The diagram is technically there, but visually it reads as a screenshot from a different site someone pasted in.&lt;/p&gt;

&lt;p&gt;That's the doc-site tax on Mermaid. The renderer is shared across every project that ships the default config, so every doc site looks the same. This post is how to get out of that shared bucket without leaving Mermaid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgzsyu5xauu598vs6rcjr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgzsyu5xauu598vs6rcjr.png" alt="A four-stage flow showing Markdown or MDX flowing into the Docusaurus or VitePress build, into a Mermaid renderer, and out to the reader's browser" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The path a Mermaid block takes from your repo to the reader. Every stage after "Markdown" is somewhere you can influence the visual — most people only ever touch the first one.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the rendering actually happens
&lt;/h2&gt;

&lt;p&gt;Both Docusaurus and VitePress bundle a client-side Mermaid runtime. When the doc site builds, fenced &lt;code&gt;mermaid&lt;/code&gt; blocks stay as source text in the generated HTML; a small JS bundle on the page finds them at load time and calls &lt;code&gt;mermaid.render()&lt;/code&gt; to swap the source for an inline SVG.&lt;/p&gt;

&lt;p&gt;This matters because the theme decision runs at three different altitudes, and the trick is knowing which one applies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;In the source&lt;/strong&gt; — a &lt;code&gt;%%{init}%%&lt;/code&gt; block at the top of one Mermaid block, applied to that block only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In the site config&lt;/strong&gt; — one Mermaid config passed to the doc-site plugin, applied to every block.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outside the renderer entirely&lt;/strong&gt; — pre-render each diagram to SVG and embed the image, bypassing the client Mermaid bundle.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each altitude trades off different things: reach, consistency, and how much control you have over the styling. I'll walk all three.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw994ca03wkd9prmt57ry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw994ca03wkd9prmt57ry.png" alt="A vertical five-step lifecycle showing a fenced Mermaid block being parsed by the doc site, handed to the client-side Mermaid bundle, converted to inline HTML and SVG, and finally rendered in the reader's viewport" width="800" height="667"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Where the Mermaid render happens in a doc site. The theme decision can land at any of these steps; the higher up you push it, the more it applies to.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Path 1: enable Mermaid, accept defaults
&lt;/h2&gt;

&lt;p&gt;Both frameworks make the enable-Mermaid step short. This is the ten-minute baseline every subsequent choice builds on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docusaurus
&lt;/h3&gt;

&lt;p&gt;Install the official Mermaid theme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @docusaurus/theme-mermaid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;docusaurus.config.js&lt;/code&gt;, enable it and switch on the Markdown flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;mermaid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;themes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@docusaurus/theme-mermaid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Every &lt;code&gt;mermaid&lt;/code&gt; block in your MDX files now renders. Docusaurus ships this as a first-party theme, so there's no third-party plugin to babysit through major version bumps.&lt;/p&gt;

&lt;h3&gt;
  
  
  VitePress
&lt;/h3&gt;

&lt;p&gt;VitePress doesn't ship Mermaid built in, but the community plugin has been stable for years. Install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; vitepress-plugin-mermaid mermaid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;.vitepress/config.ts&lt;/code&gt;, wrap your existing config with &lt;code&gt;withMermaid&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;withMermaid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vitepress-plugin-mermaid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;withMermaid&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// your existing vitepress config...&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My Docs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;…&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mermaid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// mermaid config goes here — leave empty for defaults&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;mermaid&lt;/code&gt; key is where every theme decision at the site-config altitude lives. Empty object = Mermaid's default look, which is the same pastel you're trying to escape from. Which brings us to path 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Path 2: keep Mermaid, pick a theme once
&lt;/h2&gt;

&lt;p&gt;Mermaid has five built-in themes: &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;neutral&lt;/code&gt;, &lt;code&gt;dark&lt;/code&gt;, &lt;code&gt;forest&lt;/code&gt;, and &lt;code&gt;base&lt;/code&gt;. The first four are pre-set palettes; &lt;code&gt;base&lt;/code&gt; is the one you use as a foundation when you want to override individual variables.&lt;/p&gt;

&lt;p&gt;Two ways to apply them.&lt;/p&gt;

&lt;h3&gt;
  
  
  The site-config way (the one you actually want)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Docusaurus&lt;/strong&gt; takes a &lt;code&gt;themeConfig.mermaid&lt;/code&gt; object with two useful keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;mermaid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;themes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@docusaurus/theme-mermaid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;themeConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;mermaid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;neutral&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;theme&lt;/code&gt; accepts light/dark variants matched to the site's colour mode. &lt;code&gt;neutral&lt;/code&gt; is a good pick if the default pastel bothers you but you don't want to design a palette yourself — it's monochrome, so it never fights the site's brand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VitePress&lt;/strong&gt; takes the same options nested under the &lt;code&gt;mermaid&lt;/code&gt; key of the &lt;code&gt;withMermaid&lt;/code&gt; wrapper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;withMermaid&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;mermaid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;forest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;themeVariables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;primaryColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#f8fafc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;primaryTextColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#1e293b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;primaryBorderColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#cbd5e1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lineColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#64748b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ui-sans-serif, system-ui, sans-serif&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: VitePress forces the dark Mermaid theme in dark mode regardless of what you set here — this comes from the plugin, not your config. If you need site-config dark control, use per-page &lt;code&gt;mermaidTheme:&lt;/code&gt; frontmatter (see below) as an override.&lt;/p&gt;

&lt;p&gt;For both, if you want an actually opinionated look, use &lt;code&gt;theme: 'base'&lt;/code&gt; and set &lt;code&gt;themeVariables&lt;/code&gt;. That combination is the escape hatch: &lt;code&gt;base&lt;/code&gt; disables Mermaid's bundled palettes so your variable overrides stop being silently no-op'd. The five variables that carry 80% of the aesthetic are &lt;code&gt;primaryColor&lt;/code&gt;, &lt;code&gt;primaryTextColor&lt;/code&gt;, &lt;code&gt;primaryBorderColor&lt;/code&gt;, &lt;code&gt;lineColor&lt;/code&gt;, and &lt;code&gt;fontFamily&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The per-block way (avoid if you can)
&lt;/h3&gt;

&lt;p&gt;You can also drop &lt;code&gt;%%{init}%%&lt;/code&gt; at the top of a single block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;%%{init: { "theme": "base", "themeVariables": { "primaryColor": "#f1f5f9" } }}%%
flowchart LR
  A[Request] --&amp;gt; B[Handler] --&amp;gt; C[Response]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;VitePress additionally supports per-page overrides via frontmatter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;mermaidTheme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;forest&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Auth architecture&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Per-block init is fine for one diagram that needs to look different — an on-call runbook that should read as an alert, a post-mortem where you want a warmer palette. It's a trap when you use it as the &lt;em&gt;default&lt;/em&gt; styling mechanism. Every new block needs the same prelude pasted in. Six months later, half the diagrams have the prelude and half don't, and the ones that don't render as the pastel you were trying to get rid of.&lt;/p&gt;

&lt;p&gt;The rule I use: if the styling belongs on more than one block, it belongs in the site config. Only reach for &lt;code&gt;%%{init}%%&lt;/code&gt; for the diagram that's genuinely different.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scaling ceiling for path 2
&lt;/h2&gt;

&lt;p&gt;Path 2 gets you a long way. For most doc sites, "pick &lt;code&gt;neutral&lt;/code&gt; and set a font family" is enough — the diagrams stop looking generic, they match the site's typography, and you don't have to think about it again.&lt;/p&gt;

&lt;p&gt;Three signals it's not enough:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;You want the same diagrams rendered consistently across your doc site, the project README on GitHub, and social share previews.&lt;/strong&gt; Mermaid's site config only reaches diagrams inside your Docusaurus/VitePress site. GitHub uses its own hardcoded Mermaid theme; social preview crawlers don't run the Mermaid bundle at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need control over layout, not just palette.&lt;/strong&gt; Mermaid's theme variables let you change colours and fonts. Node shape, edge routing style, spacing between subgraphs, marker size — those are the layout engine's job, and the built-in themes don't expose them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You want the doc-site build to stay fast.&lt;/strong&gt; The Mermaid runtime bundle isn't tiny; on a docs page with a dozen fenced blocks, the JS parse + client render is measurable in the Lighthouse "unused JavaScript" panel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When any of those apply, path 3 is worth twenty minutes of setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffw3vv4j5vcxi01zkburw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffw3vv4j5vcxi01zkburw.png" alt="A branching flowchart showing a docs repo splitting into three parallel paths — defaults, per-block init prelude, and renderer picked once — all converging back on the same rendered pages" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Three altitudes for the theme decision. The right one is whichever matches how many diagrams the choice needs to reach.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Path 3: swap the renderer, embed the SVG
&lt;/h2&gt;

&lt;p&gt;The idea: stop asking the doc site's Mermaid runtime to render at all. Pre-render each diagram to SVG somewhere else, then reference the URL as a regular &lt;code&gt;&amp;lt;img src&amp;gt;&lt;/code&gt;. The doc site treats it as any other image — no bundle weight, no theme inheritance, no client parse.&lt;/p&gt;

&lt;p&gt;The Web UI is where I'd start. Paste a Mermaid block into the &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;Beauty Diagram editor&lt;/a&gt;, cycle through the nine production themes — &lt;code&gt;classic&lt;/code&gt;, &lt;code&gt;modern&lt;/code&gt;, &lt;code&gt;atlas&lt;/code&gt;, &lt;code&gt;blueprint&lt;/code&gt;, &lt;code&gt;memphis&lt;/code&gt;, &lt;code&gt;obsidian&lt;/code&gt;, &lt;code&gt;slate&lt;/code&gt;, &lt;code&gt;brutalist&lt;/code&gt;, &lt;code&gt;atelier&lt;/code&gt; — and pick the one that fits the doc's mood. Save the share; the resulting URL is a hotlinkable SVG that renders in any Markdown or MDX file. &lt;em&gt;(Disclosure: I work on Beauty Diagram.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For power users and CI setups, the CLI has an &lt;code&gt;embed-url&lt;/code&gt; command that skips the browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @beauty-diagram/cli embed-url auth-flow.mmd &lt;span class="nt"&gt;--theme&lt;/span&gt; atelier
&lt;span class="c"&gt;# → https://www.beauty-diagram.com/s/abc123.svg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a Docusaurus or VitePress markdown file, that URL becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Auth flow&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://www.beauty-diagram.com/s/abc123.svg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The image renders inline; the doc site's Mermaid bundle doesn't need to run for this block; the render is deterministic from the source; and the same URL works on GitHub, in Notion, in a social preview crawl. One fewer thing depending on the doc site's runtime.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5bc35v7aqbos93erv0je.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5bc35v7aqbos93erv0je.png" alt="A four-node horizontal flow showing Mermaid source going through bd embed-url to a hotlinkable SVG URL and finally into a Docusaurus / VitePress page" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The embed-URL flow. The renderer is the CLI; the doc site is just serving an image.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Two examples of what the themes look like on the same five-node flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiz6um0yrwzptii2kkn5c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiz6um0yrwzptii2kkn5c.png" alt="The same auth flow rendered in Beauty Diagram's Blueprint theme — cyan-tinted technical drawing feel, bolder strokes" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Blueprint. For engineering deep-dives where the diagram should read as a schematic.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0vmx3fyakc8w5vh2xttb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0vmx3fyakc8w5vh2xttb.png" alt="The same auth flow rendered in Beauty Diagram's Atelier theme — warm neutral palette, editorial feel" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Atelier. For product docs and launch pages where you want the diagram to sit next to prose without shouting.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Same source, different renderer, no &lt;code&gt;mermaid&lt;/code&gt; fenced block on the page at all. The doc site's job shrinks to "serve markdown with an image tag".&lt;/p&gt;

&lt;h2&gt;
  
  
  When each path is right
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Path 1 (defaults)&lt;/th&gt;
&lt;th&gt;Path 2 (site config)&lt;/th&gt;
&lt;th&gt;Path 3 (embed URL)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;One-off internal wiki&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team doc site with a design language&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Diagrams shared to README + Notion + docs&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Care about bundle size on doc pages&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Want per-diagram layout control&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prefer everything as code in the repo&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The paths aren't exclusive. In practice I use path 2 for 90% of blocks (&lt;code&gt;neutral&lt;/code&gt; theme, one font-family override) and path 3 for the 10% that need to travel outside the doc site — the architecture diagram that's referenced from the README, the sequence diagram that shows up in a launch tweet, the flow chart that gets pasted into a Notion doc for the ops team.&lt;/p&gt;

&lt;p&gt;The way to know you're using path 2 well: you haven't touched the Mermaid config in six months and the diagrams still look intentional. The way to know you need path 3: you've started drafting the same diagram twice — once in the doc site, once as a rendered PNG for the README.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Going further: pick one theme; every Mermaid block re-renders through it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.beauty-diagram.com" rel="noopener noreferrer"&gt;Beauty Diagram&lt;/a&gt; is what I use as the renderer when I want a Mermaid block to render consistently across the doc site, the README, and Notion — paste source into the web editor, cycle through nine production themes, then keep the same theme via a hotlinkable SVG URL or the CLI. &lt;em&gt;(Disclosure: I work on it.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;→ Try the editor&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;Three takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enabling Mermaid in Docusaurus or VitePress is the ten-minute step, not the win.&lt;/strong&gt; The default look is what everyone else's doc site ships. Pick a theme in the site config — even &lt;code&gt;neutral&lt;/code&gt; is better than the default pastel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Push the theme decision as high as it will go.&lt;/strong&gt; Per-block &lt;code&gt;%%{init}%%&lt;/code&gt; is fine for exceptions; the &lt;em&gt;default&lt;/em&gt; styling belongs in &lt;code&gt;themeConfig.mermaid&lt;/code&gt; (Docusaurus) or the &lt;code&gt;mermaid&lt;/code&gt; key of &lt;code&gt;withMermaid&lt;/code&gt; (VitePress). One place to change; every block picks it up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When the diagram needs to leave the doc site — README, Notion, social — swap the renderer entirely.&lt;/strong&gt; A hotlinkable SVG URL doesn't care what site is embedding it, and the doc-site build stays lean.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpn8nxw7jcxmixrq4wav7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpn8nxw7jcxmixrq4wav7.png" alt="A four-step recap flow: enable Mermaid, pick a theme once, skip per-block init, ship the doc site" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The shortest path through this post: enable, theme once, resist the &lt;code&gt;%%{init}%%&lt;/code&gt; prelude, ship.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If this was useful, drop a ❤️ and follow — I'm posting weekly on diagrams, docs, and developer ergonomics. Next week: &lt;strong&gt;Convert draw.io Files to Production-Ready SVG (Without the Default Look)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What's the ugliest default Mermaid diagram currently sitting in a doc site you own? I'm curious whether the pastel-on-white default is universally hated or whether some people actually pick it on purpose.&lt;/p&gt;

</description>
      <category>mermaid</category>
      <category>docusaurus</category>
      <category>vitepress</category>
      <category>documentation</category>
    </item>
    <item>
      <title>10 Mermaid Tricks I Wish I'd Known Before Drawing 200 Diagrams</title>
      <dc:creator>Levi Liu</dc:creator>
      <pubDate>Mon, 29 Jun 2026 18:07:27 +0000</pubDate>
      <link>https://dev.to/levi_liu/10-mermaid-tricks-i-wish-id-known-before-drawing-200-diagrams-21kj</link>
      <guid>https://dev.to/levi_liu/10-mermaid-tricks-i-wish-id-known-before-drawing-200-diagrams-21kj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
Most people learn Mermaid by copy-pasting a flowchart from a tutorial, tweaking it once, and then never going further. The next ten tricks — subgraph zones, classDef inheritance, edge label markdown, init theme variables, click handlers — are the ones that took me from "Mermaid works" to "Mermaid actually communicates something". Every one of them is a vanilla Mermaid feature; no plugins, no forks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How I got here
&lt;/h2&gt;

&lt;p&gt;I've shipped somewhere north of 200 Mermaid diagrams into READMEs, design docs, runbooks, and onboarding decks over the last two years. The first 50 were &lt;code&gt;flowchart LR&lt;/code&gt; and four nodes. The next 100 were the same thing in slightly different colours.&lt;/p&gt;

&lt;p&gt;The last 50 were different — same syntax, but the diagrams stopped being placeholder visuals and started being something a reader could navigate without three paragraphs of caption underneath. The difference wasn't a new tool. It was a handful of Mermaid features I'd seen in the docs, skipped past, and only came back to when I got tired of the same &lt;code&gt;flowchart LR&lt;/code&gt; look.&lt;/p&gt;

&lt;p&gt;This post is those features. Each one ends with the code I actually paste into doc PRs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fac2i8bd0m10cje657t3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fac2i8bd0m10cje657t3h.png" alt="A concept map: " width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The shape of the rest of this post. Three groups; ten tricks; pick the three that apply to whatever fenced block is in front of you today.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Comments with &lt;code&gt;%%&lt;/code&gt; (yes, inside the diagram)
&lt;/h2&gt;

&lt;p&gt;The first time I saw a colleague's flowchart with leading lines like &lt;code&gt;%% retry path lives in worker.ts&lt;/code&gt;, I thought they'd broken the syntax. They hadn't — Mermaid treats &lt;code&gt;%%&lt;/code&gt; as a single-line comment anywhere in the source.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
  %% Source: docs/architecture/auth.md §3
  U[User] --&amp;gt; A[Auth]
  A --&amp;gt; S[Session]
  %% Session expiry policy: 30d sliding window
  S --&amp;gt; P[Profile]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's invisible in the rendered output, but if you're using Mermaid as documentation in a long-lived repo, comments are the difference between a diagram a future maintainer can update and a diagram they rewrite from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Edge labels carry weight — use them
&lt;/h2&gt;

&lt;p&gt;The default way to label an edge is &lt;code&gt;A -- text --&amp;gt; B&lt;/code&gt;. You'll see this in every tutorial. What the tutorials skip: edge labels accept Mermaid's full text styling, including &lt;code&gt;&amp;lt;br/&amp;gt;&lt;/code&gt; for line breaks and inline backticks for code voice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
  R[Request] -- "validate&amp;lt;br/&amp;gt;(zod)" --&amp;gt; H[Handler]
  H -- "200 OK&amp;lt;br/&amp;gt;+ session" --&amp;gt; C[Client]
  H -- "4xx&amp;lt;br/&amp;gt;+ error code" --&amp;gt; C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trick: when a flow has two edges between the same pair of nodes (happy path + error path), labels with the response shape make the diagram readable without a separate legend.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;code&gt;linkStyle&lt;/code&gt; for per-edge visual hierarchy
&lt;/h2&gt;

&lt;p&gt;Every edge in a default flowchart looks the same. That works for three nodes. It stops working at six, where the reader can't tell which path is the main one.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;linkStyle&lt;/code&gt; indexes into the edges in declaration order (0-based) and lets you re-style any of them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
  R[Request] --&amp;gt; V{Valid?}
  V -- yes --&amp;gt; H[Handler]
  V -- no --&amp;gt; E[Reject 400]
  H --&amp;gt; S[(Storage)]
  S --&amp;gt; O[Response]
  linkStyle 0,2,4,5 stroke:#2563eb,stroke-width:2.5px
  linkStyle 3 stroke:#ef4444,stroke-width:1.5px,stroke-dasharray:4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The happy path now reads as one continuous thread; the error path falls back as a dashed crimson aside. The reader's eye routes itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Per-node &lt;code&gt;style&lt;/code&gt; for the one node that matters
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;style &amp;lt;id&amp;gt; &amp;lt;css&amp;gt;&lt;/code&gt; styles one node directly. Most useful for the node a diagram is really about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
  A[Plan] --&amp;gt; B[Build] --&amp;gt; C[Test] --&amp;gt; D[Ship]
  style D fill:#16a34a,stroke:#14532d,color:#fff,stroke-width:2px
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't style every node. The whole point of a per-node style is that it's an exception — the reader's eye lands on it because it doesn't match the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;code&gt;classDef&lt;/code&gt; + &lt;code&gt;class&lt;/code&gt; — styling that scales
&lt;/h2&gt;

&lt;p&gt;Once you have three nodes that should share a style, &lt;code&gt;style&lt;/code&gt; per node gets repetitive. &lt;code&gt;classDef&lt;/code&gt; is the Mermaid way to define a reusable style and apply it by class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
  R[Request] --&amp;gt; A[Auth]
  A --&amp;gt; S[Session]
  S --&amp;gt; H[Handler]
  H --&amp;gt; D[(Database)]

  classDef external fill:#e0f2fe,stroke:#0369a1,color:#0c4a6e;
  classDef storage  fill:#fef3c7,stroke:#a16207,color:#78350f;

  class R external
  class D storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two lines of classDef, two &lt;code&gt;class&lt;/code&gt; assignments, and the diagram now teaches the reader where each component lives (external surface vs persistent storage) without a single label change.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. classDef inheritance: stack multiple classes on one node
&lt;/h2&gt;

&lt;p&gt;This one took me a year to find in the docs. &lt;code&gt;class&lt;/code&gt; accepts multiple class names, comma-separated, and Mermaid merges them in declaration order — later classes win on conflicts. So you can layer &lt;strong&gt;role&lt;/strong&gt; (external / internal / storage) onto &lt;strong&gt;state&lt;/strong&gt; (healthy / degraded / down) without writing six combined classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
  A[Auth] --&amp;gt; S[Session]
  S --&amp;gt; D[(DB)]

  classDef storage fill:#fef3c7,stroke:#a16207;
  classDef degraded stroke:#dc2626,stroke-width:3px,stroke-dasharray:4;

  class D storage,degraded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The DB node renders with the storage fill (from &lt;code&gt;storage&lt;/code&gt;) and the degraded stroke (from &lt;code&gt;degraded&lt;/code&gt;). Adding a "down" state is one more classDef plus a comma in the right &lt;code&gt;class&lt;/code&gt; line — no exponential blowup.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Subgraphs as zones, not boxes
&lt;/h2&gt;

&lt;p&gt;Most diagrams use &lt;code&gt;subgraph&lt;/code&gt; as a way to draw a box around three nodes. It's worth more than that. Subgraphs accept their own direction, their own classDef, and their own internal layout — which means you can use them to split a diagram into &lt;strong&gt;zones&lt;/strong&gt; the reader navigates one at a time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
  subgraph Edge[Edge]
    R[Request] --&amp;gt; V[Validator]
  end
  subgraph Core[Core service]
    V --&amp;gt; H[Handler]
    H --&amp;gt; Q[Queue]
  end
  subgraph Async[Async workers]
    Q --&amp;gt; W[Worker]
    W --&amp;gt; S[(Storage)]
  end

  classDef zone fill:#f8fafc,stroke:#cbd5e1,stroke-dasharray:6,color:#475569;
  class Edge,Core,Async zone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The subgraph title becomes a section header. The dashed border tells the reader "this is a zone, not a node." And because Mermaid lays out edges across subgraph boundaries, you get a flow that reads top-to-bottom &lt;strong&gt;and&lt;/strong&gt; side-by-side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fij0asp35kg349j1p2k3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fij0asp35kg349j1p2k3k.png" alt="Three-zone flow chart: Edge (Request, Validator) → Core service (Handler, Queue) → Async workers (Worker, Storage), rendered with dashed zone borders" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The same set of nodes you'd draw flat, but grouped into "where does this code live" zones. The reader can scan the boundaries before they read the edges.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Click handlers — Mermaid as navigation
&lt;/h2&gt;

&lt;p&gt;This is the trick that turned my docs from static images into navigation surfaces. &lt;code&gt;click &amp;lt;id&amp;gt; &amp;lt;url&amp;gt; "&amp;lt;tooltip&amp;gt;"&lt;/code&gt; makes a node clickable in any Mermaid renderer that supports it (GitHub does, Notion partially, doc sites like Docusaurus and VitePress all do):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
  R[Request] --&amp;gt; A[Auth] --&amp;gt; S[Session] --&amp;gt; H[Handler]

  click A "https://github.com/acme/api/blob/main/src/auth.ts" "src/auth.ts"
  click S "https://github.com/acme/api/blob/main/src/session.ts" "src/session.ts"
  click H "https://github.com/acme/api/blob/main/src/handler.ts" "src/handler.ts"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a README rendered on GitHub, every node in that diagram is a link to the file it represents. The architecture diagram becomes the index for new contributors — they can scan the shape, then click straight into the code.&lt;/p&gt;

&lt;p&gt;Tooltips alone (no URL) are also legal: &lt;code&gt;click NodeId "Tooltip text"&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Theme variables via &lt;code&gt;%%{init}%%&lt;/code&gt; — when you don't want the defaults but don't want a tool
&lt;/h2&gt;

&lt;p&gt;You can adjust Mermaid's theme inline at the top of any diagram block. The full set of variables is documented in &lt;a href="https://mermaid.js.org/config/theming.html" rel="noopener noreferrer"&gt;the Mermaid theming reference&lt;/a&gt;, but for most flows you only need 4 or 5:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#1e293b",
    "primaryTextColor": "#f1f5f9",
    "primaryBorderColor": "#334155",
    "lineColor": "#64748b",
    "fontFamily": "ui-sans-serif, system-ui, sans-serif"
  }
}}%%
flowchart LR
  R[Request] --&amp;gt; H[Handler] --&amp;gt; D[(Database)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;theme: base&lt;/code&gt; is the magic word — it disables Mermaid's bundled palettes so your variables actually take effect. Without it, Mermaid keeps applying its &lt;code&gt;default&lt;/code&gt; theme on top of your overrides and most of them silently no-op.&lt;/p&gt;

&lt;p&gt;The trade-off: every Mermaid block in the same doc needs its own init prelude (they don't inherit), and the prelude doesn't carry across rendering surfaces. Which is the cleanest segue I can give into trick 10.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Pick a theme once at the &lt;strong&gt;renderer&lt;/strong&gt;, not per-block
&lt;/h2&gt;

&lt;p&gt;Eight tricks in, you have a lot of options for in-block styling. The opposite move is to stop styling in the block at all, and pick one theme at the rendering layer — so every fenced &lt;code&gt;mermaid&lt;/code&gt; block in your repo (or your vault, or your doc site) renders consistently without a per-block init prelude.&lt;/p&gt;

&lt;p&gt;Three open-source ways to do this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub READMEs&lt;/strong&gt;: limited — GitHub forces its own Mermaid theme. The escape hatch is to ship rendered SVGs alongside the source (covered in the &lt;a href="https://www.beauty-diagram.com/blog/beautify-markdown-docs-with-cli" rel="noopener noreferrer"&gt;docs CLI post&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docusaurus / VitePress&lt;/strong&gt;: their Mermaid integrations both accept a theme config; set it once in the site config and every block picks it up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local preview&lt;/strong&gt; (Obsidian, VS Code, Cursor): the editor's bundled Mermaid renderer ships one theme. Switching it is plugin territory (covered in the &lt;a href="https://www.beauty-diagram.com/blog/beautify-mermaid-in-obsidian-and-vscode" rel="noopener noreferrer"&gt;in-editor post&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What this trick really is: a reminder that the more you push into per-block init blocks, the harder your diagrams are to re-theme as a set. If you find yourself pasting the same &lt;code&gt;%%{init}%%&lt;/code&gt; line into every block, the theme belongs at the renderer.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;When the renderer is the right place to fix it: Pick one theme; every Mermaid block re-renders through it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.beauty-diagram.com" rel="noopener noreferrer"&gt;Beauty Diagram&lt;/a&gt; is what I use as the renderer layer when I want consistent Mermaid output across the canonical doc, the embed, and the editor preview — paste source into the web editor, cycle through nine production themes, then keep the same theme via the Obsidian plugin, the VS Code extension, or the CLI for doc repos. The themes are the only knob; you pick a different one rather than tuning the current one. &lt;em&gt;(Disclosure: I work on it.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;→ Try the editor&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;The Web editor is the fastest way to feel the difference — paste a Mermaid block, click through &lt;code&gt;classic&lt;/code&gt;, &lt;code&gt;modern&lt;/code&gt;, &lt;code&gt;atlas&lt;/code&gt;, &lt;code&gt;blueprint&lt;/code&gt;, &lt;code&gt;memphis&lt;/code&gt;, &lt;code&gt;obsidian&lt;/code&gt;, &lt;code&gt;slate&lt;/code&gt;, &lt;code&gt;brutalist&lt;/code&gt;, &lt;code&gt;atelier&lt;/code&gt;, save the one that fits the doc. For repo-wide consistency, the CLI is a one-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @beauty-diagram/cli beautify diagram.mmd &lt;span class="nt"&gt;--theme&lt;/span&gt; blueprint &lt;span class="nt"&gt;--out&lt;/span&gt; diagram.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu4zx1tfd3dbi8mnlyf92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu4zx1tfd3dbi8mnlyf92.png" alt="Same five-node flow rendered in Classic — light neutral background, clean diamond decision node, blue accent" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Classic. The "neutral office doc" baseline — fine for most internal docs, deliberately quiet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7ojetkrkojie84az9ktr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7ojetkrkojie84az9ktr.png" alt="Same flow rendered in Blueprint — cyan-tinted technical drawing feel, bolder strokes, schematic aesthetic" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Blueprint. For engineering deep-dives where you want the diagram to read as a schematic.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feifhlo3qo6mgkoah2hyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feifhlo3qo6mgkoah2hyq.png" alt="Same flow rendered in Memphis — playful warm palette with offset shadow blocks, editorial feel" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Memphis. For docs that aren't trying to look corporate — blog posts, launch announcements, post-mortems with personality.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Same source, three rendering choices. The trick isn't the styling; it's that the source stayed identical and the renderer absorbed the visual decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the open-source tricks are enough
&lt;/h2&gt;

&lt;p&gt;Most of the time they are. If a single doc has one or two Mermaid blocks, learning &lt;code&gt;classDef&lt;/code&gt;, &lt;code&gt;linkStyle&lt;/code&gt;, and the init prelude is faster than picking up any external tool. Use the ten tricks above, ship the diagram, move on.&lt;/p&gt;

&lt;p&gt;The three signals it's worth graduating to a renderer pick (trick 10):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;You're pasting the same &lt;code&gt;%%{init}%%&lt;/code&gt; prelude into ten or more blocks.&lt;/strong&gt; That's a renderer config waiting to happen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The diagram needs to live somewhere the surface controls the theme&lt;/strong&gt; — GitHub README, Notion embed, doc site. Per-block init doesn't apply; renderer-level theming does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple contributors are editing the same diagrams.&lt;/strong&gt; Per-block init is fragile under copy-paste; renderer config is set once.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;Three things to take away:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mermaid has more in-syntax features than the tutorials cover.&lt;/strong&gt; Comments, &lt;code&gt;classDef&lt;/code&gt; inheritance, click handlers, init themes — all stock, all worth two minutes to learn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Style only the things that carry meaning.&lt;/strong&gt; Per-edge &lt;code&gt;linkStyle&lt;/code&gt;, per-node &lt;code&gt;style&lt;/code&gt;, zoned subgraphs — each one earns its keep by routing the reader's attention; default-everywhere is the failure mode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When you're pasting the same style preamble into every block, the renderer is the right place to fix it.&lt;/strong&gt; Per-block init is the open-source baseline; renderer-level theme picking is the next step up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kvzyqyxyfbdcfk5m4np.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kvzyqyxyfbdcfk5m4np.png" alt="A 4-step recap: 10 tricks → pick 3 that fit this diagram → ship the doc → skip the next round of polish" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The shortest path through the post: read once, apply 3 tricks to the diagram you're touching today, don't re-do this exercise on the same file later.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If this was useful, drop a ❤️ and follow — I'm posting weekly on diagrams, docs, and developer ergonomics. Next week: &lt;strong&gt;Adding Beautiful Diagrams to Your Docusaurus / VitePress Site&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Of these ten, which one did you already know but never use? I'm curious whether &lt;code&gt;classDef&lt;/code&gt; inheritance is rare-but-loved or just rare.&lt;/p&gt;

</description>
      <category>mermaid</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Beautify Mermaid Diagrams in Obsidian and VS Code (Without Leaving Your Editor)</title>
      <dc:creator>Levi Liu</dc:creator>
      <pubDate>Tue, 23 Jun 2026 15:00:18 +0000</pubDate>
      <link>https://dev.to/levi_liu/beautify-mermaid-diagrams-in-obsidian-and-vs-code-without-leaving-your-editor-211m</link>
      <guid>https://dev.to/levi_liu/beautify-mermaid-diagrams-in-obsidian-and-vs-code-without-leaving-your-editor-211m</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
Mermaid is great until you preview it in the editor you actually write in. Obsidian and VS Code (plus Cursor / Windsurf / VSCodium) all ship a default pastel renderer that fights the rest of your note or doc. This post walks the two install paths — Obsidian community plugin and VS Code Marketplace — shows the in-place "pick a theme, preview re-renders" loop in each, and covers the per-file front-matter knobs (&lt;code&gt;bd-share&lt;/code&gt;, &lt;code&gt;bd-width&lt;/code&gt;) that control output without leaving the editor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The "almost good enough" preview problem
&lt;/h2&gt;

&lt;p&gt;You're in Obsidian writing an architecture note. Or you're in VS Code drafting a doc PR. You paste a Mermaid block — &lt;code&gt;flowchart LR&lt;/code&gt; and four nodes — toggle preview, and the diagram appears. Functional. Readable. &lt;strong&gt;Off-key.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The default Mermaid renderer in both surfaces ships with the same pastel palette, the same flat edges, and the same uniform stroke weight that every other tool ships. In a polished note about your auth system, the diagram reads like a placeholder. The thing you were trying to communicate clearly is now the one element on the page that looks unfinished.&lt;/p&gt;

&lt;p&gt;The fix most people try first: keep editing the source in their editor, then round-trip through a web renderer for the screenshot, paste the image back, repeat on every change. The diagram stops drifting visually, but the source of truth fragments — your &lt;code&gt;.md&lt;/code&gt; file has Mermaid syntax that no longer matches the embedded image, and every edit becomes a 90-second context switch.&lt;/p&gt;

&lt;p&gt;The cleaner fix is keep the source in the editor, and put a themed renderer in the same pane. That's what this post is about.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnya83epc6ld5dhqi4kjv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnya83epc6ld5dhqi4kjv.png" alt="A 4-step flow: Mermaid source feeds an editor plugin, which produces a beautified preview, which gets saved into your vault or repo" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The in-editor loop. Source stays put; the preview pane is where the styling happens; saving the note or committing the file captures the themed output without a separate export step.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the default Mermaid theme falls flat
&lt;/h2&gt;

&lt;p&gt;Before going into the plugins, it's worth being concrete about what "off-key" means — because if the only thing wrong with the default were "I don't like the colours", a CSS tweak would solve it.&lt;/p&gt;

&lt;p&gt;Three things compound:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;One theme across every diagram type.&lt;/strong&gt; Mermaid's defaults apply the same palette to flowcharts, sequence diagrams, ER diagrams, state machines, and Gantt charts. A palette tuned for one is rarely tuned for all five.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No visual hierarchy on edges.&lt;/strong&gt; Every edge is the same stroke weight and the same colour. In a flow where some edges are "happy path" and some are "error / retry", the reader has to decode that from labels alone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defaults read as defaults.&lt;/strong&gt; Once a reader has seen the pastel-Mermaid look on three other sites that day, your diagram inherits whatever credibility (or lack of it) those other diagrams left behind.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's the same four-node flow rendered four ways — the first is roughly what Mermaid's default gives you; the next three are themes you'd pick instead:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxme12v737gxtjed83gek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxme12v737gxtjed83gek.png" alt="Mermaid default theme: four-node flow User to Auth to Session to Profile to Database, rendered in pastel blues with thin uniform edges" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The "looks like every other README" baseline. Functional, but doesn't carry weight.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1ovjgefelo1hx6f1pg1r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1ovjgefelo1hx6f1pg1r.png" alt="Same four-node flow rendered with the Blueprint theme — blueprint-paper cyan grid feel, bolder stroke, technical drawing aesthetic" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Blueprint — for engineering notes where you want the diagram to read as a schematic, not a sketch.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwqrvi0mjhx2wg3adq5an.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwqrvi0mjhx2wg3adq5an.png" alt="Same four-node flow rendered with the Obsidian theme — dark amethyst background, glowing edges, dark-mode native" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Obsidian — drops cleanly into a dark vault without re-tinting half the note around it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F64ylnmyewr6702fsnwyk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F64ylnmyewr6702fsnwyk.png" alt="Same four-node flow rendered with the Atelier theme — warm muted earth tones, soft shadows, editorial feel" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Atelier — when the note is closer to writing than to engineering documentation, and you want the diagram to match that voice.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Same source. The plugin's job is to make picking between these a one-click choice inside the editor you're already in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Path 1 — Obsidian: install from Community Plugins
&lt;/h2&gt;

&lt;p&gt;Obsidian's plugin model is the cleaner of the two. Install once, the renderer takes over every fenced &lt;code&gt;mermaid&lt;/code&gt; block in every note in every vault that has it enabled.&lt;/p&gt;

&lt;p&gt;The flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Obsidian → &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Community plugins&lt;/strong&gt; → &lt;strong&gt;Browse&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Search for &lt;strong&gt;"Beauty Diagram"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Install&lt;/strong&gt;, then &lt;strong&gt;Enable&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The plugin registers itself as a markdown post-processor for &lt;code&gt;mermaid&lt;/code&gt; code blocks. On any note with reading view (or live preview) open, fenced Mermaid blocks now render through the themed pipeline instead of Obsidian's bundled mermaid.js.&lt;/p&gt;

&lt;h3&gt;
  
  
  Picking a theme inside the vault
&lt;/h3&gt;

&lt;p&gt;Open the plugin's settings tab (Settings → Community plugins → Beauty Diagram → ⚙️). The theme picker shows the full set of production themes: &lt;code&gt;classic&lt;/code&gt;, &lt;code&gt;modern&lt;/code&gt;, &lt;code&gt;atlas&lt;/code&gt;, &lt;code&gt;blueprint&lt;/code&gt;, &lt;code&gt;memphis&lt;/code&gt;, &lt;code&gt;obsidian&lt;/code&gt;, &lt;code&gt;slate&lt;/code&gt;, &lt;code&gt;brutalist&lt;/code&gt;, &lt;code&gt;atelier&lt;/code&gt;. Pick one; every open Mermaid preview re-renders within a second.&lt;/p&gt;

&lt;p&gt;The choice is per-vault, not per-note. Your "engineering work" vault can pin Blueprint; your "personal writing" vault can pin Atelier; both behave independently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Per-note overrides via front-matter
&lt;/h3&gt;

&lt;p&gt;When one note in a vault needs a different treatment — say, you're drafting a doc for an external repo whose docs site uses a different theme — you can override at the file level via YAML front-matter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Auth handoff flow&lt;/span&gt;
&lt;span class="na"&gt;bd-theme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;blueprint&lt;/span&gt;
&lt;span class="na"&gt;bd-share&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;bd-width&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;720&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three knobs to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;bd-theme&lt;/code&gt;&lt;/strong&gt; picks one of the production themes for this single note. Wins over the vault default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;bd-share: true&lt;/code&gt;&lt;/strong&gt; (Obsidian plugin &lt;strong&gt;0.1.4&lt;/strong&gt;+) generates a hosted share URL alongside the in-vault preview, so you can drop the same diagram into a Slack thread or a GitHub comment without re-exporting. The URL appears in the preview footer; click to copy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;bd-width: 720&lt;/code&gt;&lt;/strong&gt; clamps the rendered diagram's max width. Useful in vaults with narrow note widths (or for diagrams you intend to paste into a fixed-width target). Defaults to the source's natural width.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The keys live in the note's front-matter so contributors editing the note in any markdown tool see them; they're inert outside the plugin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Path 2 — VS Code (and Cursor / Windsurf / VSCodium): install from Marketplace
&lt;/h2&gt;

&lt;p&gt;The VS Code extension covers more editors than the name suggests. The same VSIX runs in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VS Code&lt;/strong&gt; — official Marketplace install.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cursor&lt;/strong&gt; — same Marketplace; Cursor's extension panel reads from VS Code's registry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windsurf&lt;/strong&gt; — same Marketplace via Open VSX.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VSCodium&lt;/strong&gt; — install the VSIX directly (Open VSX or download from the Marketplace listing).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The install:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;View → Extensions&lt;/strong&gt; (or &lt;code&gt;Cmd-Shift-X&lt;/code&gt; / &lt;code&gt;Ctrl-Shift-X&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Search &lt;strong&gt;"Beauty Diagram"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The extension hooks the built-in markdown preview. Open any &lt;code&gt;.md&lt;/code&gt; file, hit &lt;strong&gt;Preview to the Side&lt;/strong&gt; (&lt;code&gt;Cmd-K V&lt;/code&gt;), and Mermaid blocks in that file render through the themed pipeline. No restart, no &lt;code&gt;settings.json&lt;/code&gt; edit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Picking a theme without leaving the file
&lt;/h3&gt;

&lt;p&gt;The extension contributes a status bar item — &lt;strong&gt;&lt;code&gt;Beauty Diagram: &amp;lt;current theme&amp;gt;&lt;/code&gt;&lt;/strong&gt; — at the bottom-right of the editor when a markdown file with Mermaid blocks is active. Click it, the command palette opens with all 9 themes listed, pick one, the preview re-renders.&lt;/p&gt;

&lt;p&gt;The choice persists per workspace (in &lt;code&gt;.vscode/settings.json&lt;/code&gt; under &lt;code&gt;beautyDiagram.theme&lt;/code&gt;), so your team can commit a workspace theme alongside the docs and everyone's previews match.&lt;/p&gt;

&lt;h3&gt;
  
  
  Per-file front-matter overrides
&lt;/h3&gt;

&lt;p&gt;Same shape as Obsidian, same keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;bd-theme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;modern&lt;/span&gt;
&lt;span class="na"&gt;bd-share&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;bd-width&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;960&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Mermaid block below the front-matter is unchanged — any fenced &lt;code&gt;mermaid&lt;/code&gt; block in the same file picks up these settings.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;bd-theme&lt;/code&gt;&lt;/strong&gt; overrides the workspace setting for this single file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;bd-share: true&lt;/code&gt;&lt;/strong&gt; (VS Code extension &lt;strong&gt;0.1.19&lt;/strong&gt;+) renders the same hosted share link the Obsidian plugin does. Status bar shows a copyable URL once the preview renders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;bd-width: 960&lt;/code&gt;&lt;/strong&gt; clamps the rendered width — handy when the doc will be embedded in a site with a known content column.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;bd-width&lt;/code&gt; landed in the same release (0.1.19) on the VS Code side and 0.1.4 on the Obsidian side. If you're on an older build, the front-matter key is ignored — upgrade via the extension panel / community plugins screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "no round-trip" loop, end to end
&lt;/h2&gt;

&lt;p&gt;The reason both plugins matter together is that the writing loop collapses to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Type Mermaid in your editor.&lt;/li&gt;
&lt;li&gt;Toggle preview.&lt;/li&gt;
&lt;li&gt;Cycle themes via the command palette / settings tab until the diagram fits the note.&lt;/li&gt;
&lt;li&gt;Save / commit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No browser tab. No "paste source into a web renderer, screenshot, drag image back, delete source, repeat on next edit." The source stays canonical; the preview is the design surface.&lt;/p&gt;

&lt;p&gt;For diagrams that DO need to live outside the vault — a doc embed, a Slack post, a comment on a PR — &lt;code&gt;bd-share: true&lt;/code&gt; produces a hot-linkable URL that updates when you edit the source. Same loop, one extra opt-in field per file.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Two install paths, same renderer: beautify Mermaid in the editor you already use&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.beauty-diagram.com" rel="noopener noreferrer"&gt;Beauty Diagram&lt;/a&gt; ships an Obsidian community plugin and a VS Code Marketplace extension (also works in Cursor, Windsurf, and VSCodium). Pick a theme inside the editor, render every fenced Mermaid block through it, and use the front-matter knobs when one note needs to break ranks. &lt;em&gt;(Disclosure: I work on it.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.beauty-diagram.com/integrations/obsidian" rel="noopener noreferrer"&gt;→ See the Obsidian plugin&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;If your daily writing surface is VS Code rather than Obsidian, the &lt;a href="https://www.beauty-diagram.com/integrations/vscode" rel="noopener noreferrer"&gt;VS Code extension landing&lt;/a&gt; has the same install walkthrough and a feature matrix specific to that ecosystem (workspace settings, status-bar control, multi-root behaviour).&lt;/p&gt;

&lt;h2&gt;
  
  
  When the in-editor path isn't the right path
&lt;/h2&gt;

&lt;p&gt;A few cases where you'll want to skip the plugins and stay with the open-source baseline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Your team requires a sandboxed plugin policy.&lt;/strong&gt; Some orgs lock down Obsidian community plugins entirely (or whitelist a small set). Submit a security review or stay with the bundled mermaid.js + an &lt;code&gt;init&lt;/code&gt; directive for a hand-tuned theme.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You're rendering Mermaid in a context the editor can't reach.&lt;/strong&gt; A CI step, a hosted preview environment, a server-side render of a markdown blob — none of those run inside Obsidian or VS Code. The in-editor plugins are for the author's loop, not the build pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The diagram is the doc.&lt;/strong&gt; A tutorial about Mermaid itself benefits from the reader seeing the same default render they'd get on their own setup. Theming it would obscure the lesson.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You're targeting a surface that ships its own Mermaid renderer.&lt;/strong&gt; GitHub READMEs, Notion, GitLab, some Docusaurus configurations — the surface's renderer wins regardless of what your editor previewed. The editor plugin makes drafting easier; the published output needs a different conversation (see the previous post in this series on the docs-repo workflow).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The rule of thumb: editor plugins are for the writing loop. Hosted shares and pre-rendered SVGs are for the publishing loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;Three takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The "ugly Mermaid preview" problem is solved at the editor, not at the source.&lt;/strong&gt; Don't sprinkle &lt;code&gt;init&lt;/code&gt; directives across every block; install one plugin that handles every block in the vault or workspace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One install covers more editors than you'd think.&lt;/strong&gt; Obsidian on the writing side; VS Code, Cursor, Windsurf, and VSCodium on the code-adjacent side. The renderer is the same; the install shell differs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-file front-matter is the escape hatch.&lt;/strong&gt; &lt;code&gt;bd-theme&lt;/code&gt;, &lt;code&gt;bd-share&lt;/code&gt;, &lt;code&gt;bd-width&lt;/code&gt; cover the three things you actually want to override per note: visual treatment, shareability, and embedded width.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this was useful, drop a ❤️ and follow — I'm posting weekly on diagrams, docs, and developer ergonomics. Next week: &lt;strong&gt;10 Mermaid Tricks I Wish I'd Known Before Drawing 200 Diagrams&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Which editor is your default writing surface for Mermaid — Obsidian, VS Code, or something I haven't named? I'm trying to figure out whether the next plugin should be JetBrains or Zed first.&lt;/p&gt;

</description>
      <category>mermaid</category>
      <category>obsidian</category>
      <category>vscode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Beautify Every Diagram in Your Markdown Docs with One Command</title>
      <dc:creator>Levi Liu</dc:creator>
      <pubDate>Tue, 16 Jun 2026 14:39:26 +0000</pubDate>
      <link>https://dev.to/levi_liu/beautify-every-diagram-in-your-markdown-docs-with-one-command-kdp</link>
      <guid>https://dev.to/levi_liu/beautify-every-diagram-in-your-markdown-docs-with-one-command-kdp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
A typical docs repo has dozens of Mermaid blocks scattered across markdown files, each rendering with whatever default Mermaid theme the consumer site picked, none of them consistent with each other. This post walks the two-command path — &lt;code&gt;bd extract&lt;/code&gt; to pull every fenced block out of markdown, &lt;code&gt;bd batch&lt;/code&gt; to render them all to themed SVGs, and a small markdown rewrite to embed the SVGs back via &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;. The same pipeline drops into a GitHub Actions workflow at the end. If you want to try a single file first, the &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;editor&lt;/a&gt; renders one block at a time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The state of diagrams in most docs repos
&lt;/h2&gt;

&lt;p&gt;Open any mid-sized open-source repo with substantial docs — &lt;code&gt;kubernetes/kubernetes&lt;/code&gt;, &lt;code&gt;prometheus/prometheus&lt;/code&gt;, &lt;code&gt;vercel/next.js&lt;/code&gt;. Search the markdown tree for &lt;code&gt;mermaid&lt;/code&gt; fenced blocks. You'll find 30 to 100 of them across docs, contributing guides, RFC archives, and stale design notes.&lt;/p&gt;

&lt;p&gt;Then look at how those diagrams actually render. Three observations, every time:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Most diagrams use Mermaid's default theme&lt;/strong&gt; — the pastel one with the muted blues and the soft drop-shadows. It's fine in isolation. Across 40 diagrams in a single docs site, it reads as "nobody owned this."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Some diagrams are silently broken.&lt;/strong&gt; A typo in a &lt;code&gt;flowchart&lt;/code&gt; arrow, an unclosed &lt;code&gt;subgraph&lt;/code&gt;, an &lt;code&gt;erDiagram&lt;/code&gt; field that no longer parses on the current Mermaid version. The page renders, the diagram block becomes an error message, nobody notices for six months because nobody reads the contributing guide that often.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The diagrams that DO look good are the recent ones.&lt;/strong&gt; Whoever shipped them most recently set a theme in an &lt;code&gt;init&lt;/code&gt; block at the top of the diagram. Older blocks don't have the directive. The site looks like geological strata of "whatever Mermaid theme was fashionable that quarter."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can fix all three by hand. Open every markdown file, paste each Mermaid block into a renderer, eyeball it, fix syntax errors, prepend an &lt;code&gt;init&lt;/code&gt; directive with your preferred theme, save. For a 60-file docs repo that's maybe a day of mechanical work — and it'll drift again in three months because every new contributor adds blocks without the directive.&lt;/p&gt;

&lt;p&gt;Or you can build a two-command pipeline that does this automatically and run it in CI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0uutp5bj0zwcxpe3zw1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0uutp5bj0zwcxpe3zw1.png" alt="A flowchart showing markdown docs feeding into bd extract, which feeds bd batch, which produces themed SVGs, which get embedded back into the markdown via the picture element" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The pipeline this post builds: extract every fenced diagram out of markdown, render them all in one batch, embed the SVGs back so the rendered page shows your themed version while the markdown source still holds the original code.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why bake the SVG into the page (instead of letting the site render Mermaid live)
&lt;/h2&gt;

&lt;p&gt;A reasonable counter-argument: "My doc site already renders Mermaid client-side via mermaid.js. Why pre-render at all?"&lt;/p&gt;

&lt;p&gt;Three reasons the pre-render path wins for docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consistency across surfaces.&lt;/strong&gt; Your README on GitHub, your VS Code marketplace listing, your npm page, your Docusaurus site, your printed PDF export — all render Mermaid differently (or not at all). A pre-rendered SVG looks the same everywhere because there's no rendering left to do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bundle weight.&lt;/strong&gt; mermaid.js minified is around 600 KB. If the only reason your docs ship it is the four diagrams on your architecture page, you're paying a meaningful payload tax for every visitor of every other page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The diagram becomes a real asset.&lt;/strong&gt; Once it's an SVG on disk you can review it in PRs (the diff is the SVG file, which renders in GitHub's PR view), you can run an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; accessibility check on it, and you can link to it from outside the docs site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pipeline below keeps the Mermaid source in the markdown — so contributors still edit Mermaid, not SVG — but renders to an SVG asset alongside it. The &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; embed shows the SVG to readers; the source block becomes a collapsed &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; for anyone who wants to see the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — &lt;code&gt;bd extract&lt;/code&gt; pulls every diagram out of markdown
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @beauty-diagram/cli extract docs/&lt;span class="k"&gt;**&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.md &lt;span class="nt"&gt;--assets-dir&lt;/span&gt; docs/_diagrams
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This walks every markdown file matching the glob, finds every fenced &lt;code&gt;mermaid&lt;/code&gt; (and &lt;code&gt;plantuml&lt;/code&gt;) block, and writes each one to a standalone source file under the assets directory. Filename is derived from the markdown file path plus a stable hash of the block contents, so re-running on an unchanged docs tree is a no-op.&lt;/p&gt;

&lt;p&gt;A typical output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs/_diagrams/
  architecture/
    overview-a3f9c1.mmd
    overview-b8e240.mmd
    auth-flow-7c2105.mmd
  contributing/
    pr-lifecycle-91d8a2.mmd
  guides/
    request-path-4e1c80.mmd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few flags worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--dry-run&lt;/code&gt; lists what would be written without touching disk. Run this first to see how many blocks your repo actually has.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--clean&lt;/code&gt; removes orphaned source files in the assets directory before extracting — useful when blocks get deleted from markdown and you don't want stale &lt;code&gt;.mmd&lt;/code&gt; files lying around.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--concurrency &amp;lt;n&amp;gt;&lt;/code&gt; controls parallel parsing for very large doc trees. The default is sensible; only touch it if you're indexing thousands of files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a block has a syntax error, &lt;code&gt;bd extract&lt;/code&gt; still writes the source file and prints a warning. The block is real even if it's broken; the next step decides what to do with broken blocks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — &lt;code&gt;bd batch&lt;/code&gt; renders them all to themed SVGs
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @beauty-diagram/cli batch docs/_diagrams/&lt;span class="k"&gt;**&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.mmd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--out-dir&lt;/span&gt; docs/_diagrams &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--format&lt;/span&gt; svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This renders every extracted source file to an SVG sibling. Same filename, different extension. Theme is whichever one you set globally — &lt;code&gt;BEAUTY_DIAGRAM_THEME=modern&lt;/code&gt; in the environment, or passed per-file via the source's own &lt;code&gt;init&lt;/code&gt; directive.&lt;/p&gt;

&lt;p&gt;You'll get output like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ docs/_diagrams/architecture/overview-a3f9c1.svg (1142×680)
✓ docs/_diagrams/architecture/overview-b8e240.svg (980×420)
✓ docs/_diagrams/architecture/auth-flow-7c2105.svg (1240×910)
✗ docs/_diagrams/contributing/pr-lifecycle-91d8a2.mmd: parse error at line 14
✓ docs/_diagrams/guides/request-path-4e1c80.svg (860×540)

4 succeeded, 1 failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--stop-on-error&lt;/code&gt; flag flips the failure mode: by default &lt;code&gt;bd batch&lt;/code&gt; keeps going so one bad diagram doesn't tank a 200-diagram run. In CI you'll usually want &lt;code&gt;--stop-on-error&lt;/code&gt; so a broken block fails the build, which is the whole point of running this in CI to begin with.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--concurrency&lt;/code&gt; defaults to a reasonable parallelism for your CPU; raise it on a big CI runner if the batch takes long enough to matter.&lt;/p&gt;

&lt;p&gt;The "consistency" payoff lands here. The same theme renders every diagram across the entire docs tree.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4iccdm2glt8tb6t3tm0p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4iccdm2glt8tb6t3tm0p.png" alt="A four-node architecture flow — API Gateway, Auth Service, App Services, Event Bus — rendered with the modern theme" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A typical architecture diagram rendered with a single chosen theme. The consistency story is that every one of your 40 docs diagrams comes out looking like this one — same stroke weight, same palette, same edge style.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Embed the SVGs back via &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The extract / batch pair gave you SVG files. The markdown still holds the original Mermaid source. Now you decide how the rendered page should reference the asset.&lt;/p&gt;

&lt;p&gt;The cleanest pattern is &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; with the SVG as the primary source and a collapsed &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; for the original code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &amp;lt;img
    src="/_diagrams/architecture/overview-a3f9c1.svg"
    alt="High-level system architecture: API gateway, auth service, app services, and the shared event bus"
  /&amp;gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;details&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;Mermaid source&lt;span class="nt"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;mermaid
&lt;/span&gt;&lt;span class="sb"&gt;flowchart LR
  Gateway[API Gateway] --&amp;gt; Auth[Auth Service]
  Gateway --&amp;gt; App[App Services]
  App --&amp;gt; Bus[(Event Bus)]&lt;/span&gt;
&lt;span class="p"&gt;```&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/details&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why this shape:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The reader sees the SVG by default&lt;/strong&gt; — themed, crisp, no client-side rendering cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The source is one click away&lt;/strong&gt; for anyone who wants to copy it into their own diagram, file a fix, or learn from the syntax.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The markdown file remains the source of truth.&lt;/strong&gt; A contributor editing the doc edits the Mermaid block, runs the pipeline, commits both the updated source and the regenerated SVG.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most static site generators (Docusaurus, VitePress, MkDocs, Hugo, Astro) render &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; natively. GitHub's markdown renderer does too, including in PR descriptions. The pattern is portable.&lt;/p&gt;

&lt;p&gt;If you'd rather not maintain the dual source + asset embed by hand, the extract step has a &lt;code&gt;--rewrite&lt;/code&gt; mode that updates the markdown file in place — collapsing the fenced block into the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; + &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; pair on first run, leaving it alone on subsequent runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Wire it into CI so it stays beautified
&lt;/h2&gt;

&lt;p&gt;A small GitHub Actions workflow that fails any PR introducing a broken diagram or skipping the regeneration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Beautify docs&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;docs/**/*.md'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;docs/_diagrams/**'&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;beautify&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;20'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Extract diagrams from markdown&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;npx @beauty-diagram/cli extract 'docs/**/*.md' \&lt;/span&gt;
            &lt;span class="s"&gt;--assets-dir docs/_diagrams \&lt;/span&gt;
            &lt;span class="s"&gt;--clean&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Render every diagram&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;npx @beauty-diagram/cli batch 'docs/_diagrams/**/*.mmd' \&lt;/span&gt;
            &lt;span class="s"&gt;--out-dir docs/_diagrams \&lt;/span&gt;
            &lt;span class="s"&gt;--format svg \&lt;/span&gt;
            &lt;span class="s"&gt;--stop-on-error&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;BEAUTY_DIAGRAM_THEME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;modern&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Fail if anything changed&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git diff --exit-code docs/_diagrams || (&lt;/span&gt;
            &lt;span class="s"&gt;echo "::error::Diagrams are out of date. Run the beautify pipeline locally and commit the result."&lt;/span&gt;
            &lt;span class="s"&gt;exit 1&lt;/span&gt;
          &lt;span class="s"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;git diff --exit-code&lt;/code&gt; at the end is the trick. The job regenerates everything from scratch on every PR; if the output differs from what's checked in, the PR failed to run the pipeline before pushing, and the build fails. Contributors learn the workflow once and it stays automatic forever.&lt;/p&gt;

&lt;p&gt;For a &lt;code&gt;Makefile&lt;/code&gt;-driven repo, the same pattern collapses to two targets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;diagrams&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    npx @beauty-diagram/cli extract &lt;span class="s1"&gt;'docs/**/*.md'&lt;/span&gt; &lt;span class="nt"&gt;--assets-dir&lt;/span&gt; docs/_diagrams &lt;span class="nt"&gt;--clean&lt;/span&gt;
    npx @beauty-diagram/cli batch &lt;span class="s1"&gt;'docs/_diagrams/**/*.mmd'&lt;/span&gt; &lt;span class="nt"&gt;--out-dir&lt;/span&gt; docs/_diagrams &lt;span class="nt"&gt;--format&lt;/span&gt; svg &lt;span class="nt"&gt;--stop-on-error&lt;/span&gt;

&lt;span class="nl"&gt;verify-diagrams&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;diagrams&lt;/span&gt;
    git diff &lt;span class="nt"&gt;--exit-code&lt;/span&gt; docs/_diagrams
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;make diagrams&lt;/code&gt; regenerates locally; &lt;code&gt;make verify-diagrams&lt;/code&gt; is what CI calls.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;From one file to a whole repo: themed SVGs for every diagram, in one batch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.beauty-diagram.com" rel="noopener noreferrer"&gt;Beauty Diagram&lt;/a&gt;'s CLI ships extract + batch as the docs-scale pair, so the same renderer that handles a single file in the editor handles a hundred files in CI. Pick a theme once, apply it everywhere, and let the git-diff check keep contributors honest. &lt;em&gt;(Disclosure: I work on it.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;→ Try one diagram in the editor&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;The fastest way to feel the workflow is one file at a time in the &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;editor&lt;/a&gt; — paste a Mermaid block from your docs repo, pick a theme, see whether the result is the consistency you want. Once you've picked a theme you like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install once&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; @beauty-diagram/cli

&lt;span class="c"&gt;# Set the theme for the whole repo&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BEAUTY_DIAGRAM_THEME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;modern

&lt;span class="c"&gt;# Run the pipeline locally&lt;/span&gt;
npx bd extract &lt;span class="s1"&gt;'docs/**/*.md'&lt;/span&gt; &lt;span class="nt"&gt;--assets-dir&lt;/span&gt; docs/_diagrams &lt;span class="nt"&gt;--clean&lt;/span&gt;
npx bd batch &lt;span class="s1"&gt;'docs/_diagrams/**/*.mmd'&lt;/span&gt; &lt;span class="nt"&gt;--out-dir&lt;/span&gt; docs/_diagrams &lt;span class="nt"&gt;--format&lt;/span&gt; svg

&lt;span class="c"&gt;# Commit the assets and the rewritten markdown&lt;/span&gt;
git add docs/_diagrams docs/&lt;span class="k"&gt;**&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.md
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Beautify docs diagrams"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;bd beautify&lt;/code&gt;, &lt;code&gt;bd export&lt;/code&gt;, &lt;code&gt;bd extract&lt;/code&gt;, and &lt;code&gt;bd batch&lt;/code&gt; all work anonymously for rendering. The paid tier kicks in for AI features (&lt;code&gt;bd ai generate&lt;/code&gt;) and higher quotas; the docs-pipeline use case lives entirely inside the free surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  When NOT to pre-render
&lt;/h2&gt;

&lt;p&gt;A few cases where the live-Mermaid-in-the-browser path is the better trade:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Your docs site already ships mermaid.js for other reasons.&lt;/strong&gt; If the bundle cost is paid, you're not saving anything by pre-rendering. Use &lt;code&gt;init&lt;/code&gt; directives in your Mermaid blocks to set a consistent theme and call it done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diagrams change every commit.&lt;/strong&gt; A README that auto-regenerates an architecture diagram from the codebase on every push has no use for pre-rendered assets — the SVG would be stale by the next push. Live rendering at view time is the right call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You only have three diagrams.&lt;/strong&gt; The batch pipeline pays off when there are enough diagrams that consistency is the problem. Three diagrams you can keep coherent by hand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your audience needs the source visible by default.&lt;/strong&gt; A Mermaid tutorial, a "diagrams as code" RFC, a contributing guide. Pre-rendering hides the syntax behind a &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt;; if the syntax IS the point, leave it as a fenced block.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The rule of thumb: pre-render when the diagram is a doc asset (read, not edited, by most readers); live-render when the diagram is the doc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;Three takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Diagrams in docs repos drift the same way docs drift.&lt;/strong&gt; Different themes, broken blocks, no review process. The fix is the same fix you applied to docs: a build step + a CI gate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The two-command pipeline is &lt;code&gt;bd extract&lt;/code&gt; + &lt;code&gt;bd batch&lt;/code&gt;.&lt;/strong&gt; Extract pulls every fenced block to standalone source files; batch renders all of them to themed SVGs. The git-diff CI check keeps the output in sync.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embed via &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; + collapsed &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt;.&lt;/strong&gt; Reader sees the themed SVG, contributor still edits Mermaid, source of truth stays in markdown.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this was useful, drop a ❤️ and follow — I'm posting weekly on diagrams, docs, and developer ergonomics. Next week: &lt;strong&gt;Beautify Mermaid Diagrams in Obsidian and VS Code (Without Leaving Your Editor)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;How many Mermaid blocks does your docs repo have right now? Run &lt;code&gt;grep -r "mermaid" docs/ | wc -l&lt;/code&gt; and drop the number in the comments — I'm collecting "diagrams per docs repo" data and the spread is wider than you'd guess.&lt;/p&gt;

</description>
      <category>mermaid</category>
      <category>documentation</category>
      <category>cli</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Generate Mermaid from Plain English with AI (CLI Walkthrough)</title>
      <dc:creator>Levi Liu</dc:creator>
      <pubDate>Wed, 10 Jun 2026 09:43:31 +0000</pubDate>
      <link>https://dev.to/levi_liu/generate-mermaid-from-plain-english-with-ai-cli-walkthrough-4ii0</link>
      <guid>https://dev.to/levi_liu/generate-mermaid-from-plain-english-with-ai-cli-walkthrough-4ii0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
You already know &lt;code&gt;flowchart TD&lt;/code&gt; cold. You don't know &lt;code&gt;sequenceDiagram&lt;/code&gt; participant aliases, &lt;code&gt;erDiagram&lt;/code&gt; cardinality glyphs, or which state diagram dialect Mermaid is on this year. This post is a walkthrough of five prompts → five diagrams using &lt;code&gt;bd ai generate&lt;/code&gt;, plus when the AI-first path is wrong. If you want to try without installing anything, the same prompt input lives in the &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;editor&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The friction isn't drawing — it's remembering
&lt;/h2&gt;

&lt;p&gt;I've shipped probably 200 flowcharts. I can sketch a &lt;code&gt;flowchart TD&lt;/code&gt; with arrows and labels without thinking. The syntax has lived in my hands long enough that it's muscle memory.&lt;/p&gt;

&lt;p&gt;Then someone asks for a sequence diagram of the OAuth flow, and I open the Mermaid docs. Again. For the seventh time this year.&lt;/p&gt;

&lt;p&gt;That's the actual friction with diagrams-as-code: most teams write one diagram type 90% of the time and four other types maybe twice a year each. The rare types never make it into your fingers — you re-read the docs every time, hit a syntax snag, and lose ten minutes. Multiply by every infrequent diagram across a docs repo and that's a real tax.&lt;/p&gt;

&lt;p&gt;AI removes the activation energy. You describe the diagram in plain English, get back syntactically valid Mermaid, and skip straight to "does this say what I want." That's a different kind of editing — refining a draft instead of looking up glyphs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwfdi9do1gd7pdlx8orpc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwfdi9do1gd7pdlx8orpc.png" alt="A flowchart showing plain English prompt feeding into AI, producing Mermaid source, which is rendered into a polished SVG" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The path this post walks: prompt → AI → Mermaid → rendered diagram.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape of the workflow
&lt;/h2&gt;

&lt;p&gt;Two paths, same engine underneath:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;In the editor&lt;/strong&gt; — paste your prompt into the AI Generate panel at &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;/editor&lt;/a&gt;. It writes the Mermaid for you, you tweak in the source pane, you pick a theme, you export.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In the terminal&lt;/strong&gt; — &lt;code&gt;bd ai generate "&amp;lt;prompt&amp;gt;"&lt;/code&gt; prints the Mermaid to stdout. Pipe it into the renderer, redirect to a file, or paste into your README.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The editor is the right entry point if you're iterating — you can see the rendered diagram live as you refine the source. The CLI is the right surface once you know what you want and you're scripting it into a docs build, a &lt;code&gt;package.json&lt;/code&gt; task, or a CI job.&lt;/p&gt;

&lt;p&gt;The five examples below all use the CLI form so the prompts and outputs are easy to copy. Every one of them works in the editor too — paste the same prompt, get the same kind of output.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;bd ai generate&lt;/code&gt; is a paid-plan feature. Anonymous demo gives you the renderer; AI generation is gated behind a key because every call hits a model and costs money. &lt;code&gt;bd auth login&lt;/code&gt; once, set &lt;code&gt;BEAUTY_DIAGRAM_API_KEY&lt;/code&gt; in CI, done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt 1 — OAuth login (sequence diagram)
&lt;/h2&gt;

&lt;p&gt;Sequence diagrams are the textbook case for "I know what I want, I don't remember the syntax." Participants, arrows, dotted return lines, &lt;code&gt;loop&lt;/code&gt; blocks — there's just enough surface to forget between uses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bd ai generate &lt;span class="s2"&gt;"user signs in with Google OAuth: web app redirects &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
to Google's authorize endpoint, user approves, Google returns an &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
authorization code, web app exchanges the code at our API for a &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
session token"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI returns something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
  participant U as User
  participant W as Web App
  participant G as Google OAuth
  participant A as App API
  U-&amp;gt;&amp;gt;W: Click "Sign in with Google"
  W-&amp;gt;&amp;gt;G: Redirect to /authorize
  G-&amp;gt;&amp;gt;U: Consent prompt
  U-&amp;gt;&amp;gt;G: Approve scopes
  G-&amp;gt;&amp;gt;W: Authorization code
  W-&amp;gt;&amp;gt;A: Exchange code
  A-&amp;gt;&amp;gt;W: Session token
  W-&amp;gt;&amp;gt;U: Logged in
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Render it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwe785flbl59tknj9v3f3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwe785flbl59tknj9v3f3.png" alt="A sequence diagram showing the OAuth authorization-code flow between User, Web App, Google OAuth, and the App API" width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;OAuth authorization-code flow, generated from the prompt above and rendered with the &lt;code&gt;atlas&lt;/code&gt; theme.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The participants are aliased (&lt;code&gt;U as User&lt;/code&gt;, &lt;code&gt;W as Web App&lt;/code&gt;) without me having to remember the syntax. The arrows pick &lt;code&gt;-&amp;gt;&amp;gt;&lt;/code&gt; for solid calls. Two minutes from prompt to rendered diagram, of which ten seconds was renaming "App API" to "Backend" to match the codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt 2 — Multi-tenant SaaS schema (ER diagram)
&lt;/h2&gt;

&lt;p&gt;ER diagrams are the worst offender for syntax recall. Cardinality glyphs — &lt;code&gt;||--o{&lt;/code&gt;, &lt;code&gt;}o--||&lt;/code&gt;, &lt;code&gt;|o--o|&lt;/code&gt; — never live in anyone's head.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bd ai generate &lt;span class="s2"&gt;"multi-tenant SaaS database: users belong to many &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
workspaces through memberships; workspaces own projects; projects &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
contain tasks; users are also assigned to tasks"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;erDiagram
  USERS ||--o{ MEMBERSHIPS : has
  WORKSPACES ||--o{ MEMBERSHIPS : has
  WORKSPACES ||--o{ PROJECTS : owns
  PROJECTS ||--o{ TASKS : contains
  USERS ||--o{ TASKS : assigned
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0d513ne15wsr02g2yxvq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0d513ne15wsr02g2yxvq.png" alt="An ER diagram showing the relationships between Users, Memberships, Workspaces, Projects, and Tasks in a multi-tenant SaaS schema" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A multi-tenant SaaS schema, generated from a one-sentence prompt and rendered with the &lt;code&gt;blueprint&lt;/code&gt; theme.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The model picked the right cardinality glyphs without you typing them. It also picked an entity-naming convention (uppercase, plural) and stuck with it across all five entities. That's the kind of consistency tax you'd otherwise pay manually.&lt;/p&gt;

&lt;p&gt;When this matters: the diagram is wrong if &lt;code&gt;MEMBERSHIPS&lt;/code&gt; should have been an attribute on &lt;code&gt;USERS&lt;/code&gt; instead of a join entity. The AI guessed "many-to-many through membership", which is the right call for most multi-tenant SaaS — but if you're modeling something else, you'll edit. That's the workflow: get a draft fast, refine the parts that don't match your domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt 3 — CI/CD pipeline (flowchart)
&lt;/h2&gt;

&lt;p&gt;Yes, even the flowchart you can write blindfolded benefits from a prompt when the diagram has six branches and a manual gate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bd ai generate &lt;span class="s2"&gt;"GitHub Actions pipeline: PR merged to main triggers &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
tests; if tests pass build a container image, deploy to staging, &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
require manual approval, then deploy to production. If tests fail, &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
notify the PR author."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
  PR[PR merged to main] --&amp;gt; Test[Run tests]
  Test --&amp;gt;|pass| Build[Build image]
  Test --&amp;gt;|fail| Notify[Notify author]
  Build --&amp;gt; Stage[Deploy to staging]
  Stage --&amp;gt; Gate{Manual approval}
  Gate --&amp;gt;|approve| Prod[Deploy to prod]
  Gate --&amp;gt;|reject| Hold[Hold release]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xl53x2yu2bnz7au3ml1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xl53x2yu2bnz7au3ml1.png" alt="A top-down flowchart showing a CI/CD pipeline from PR merge through tests, image build, staging deploy, manual approval, and prod deploy, with branches for test failure and approval rejection" width="800" height="667"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The CI/CD pipeline, with the failure branches the prompt asked for. Rendered with the &lt;code&gt;modern&lt;/code&gt; theme.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Two details worth noting. First, the AI chose &lt;code&gt;{Manual approval}&lt;/code&gt; (decision diamond) instead of &lt;code&gt;[Manual approval]&lt;/code&gt; (rectangle) for the gate — the right shape for a yes/no branch. Second, it used &lt;code&gt;--&amp;gt;|pass|&lt;/code&gt; for labelled edges instead of breaking the label onto a separate line, which is the cleaner Mermaid idiom.&lt;/p&gt;

&lt;p&gt;You could have written this. The question is whether you want to spend three minutes typing it or thirty seconds prompting it. For a diagram that's going in your team's onboarding doc and won't change for six months, the prompt path is the better trade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt 4 — Order lifecycle (state diagram)
&lt;/h2&gt;

&lt;p&gt;State machines are another "syntax-rare" category. &lt;code&gt;[*] --&amp;gt; X&lt;/code&gt;, transitions with labels, the difference between &lt;code&gt;stateDiagram&lt;/code&gt; and &lt;code&gt;stateDiagram-v2&lt;/code&gt; (the v2 syntax is what Mermaid currently maintains).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bd ai generate &lt;span class="s2"&gt;"order lifecycle state machine: starts in cart, &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
becomes placed on checkout, paid when payment succeeds, shipped &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
when fulfilled, delivered when the carrier confirms. From paid, &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
the customer can cancel to refunded."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stateDiagram-v2
  [*] --&amp;gt; Cart
  Cart --&amp;gt; Placed: Checkout
  Placed --&amp;gt; Paid: Payment OK
  Paid --&amp;gt; Shipped: Fulfilled
  Shipped --&amp;gt; Delivered: Carrier confirms
  Delivered --&amp;gt; [*]
  Paid --&amp;gt; Refunded: Customer cancels
  Refunded --&amp;gt; [*]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5zolqs6s267f1ftze90.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5zolqs6s267f1ftze90.png" alt="A state diagram showing an order moving from Cart through Placed, Paid, Shipped, Delivered, with a branch to Refunded from Paid" width="800" height="667"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Order lifecycle states, with the refund branch the prompt described. Rendered with the &lt;code&gt;slate&lt;/code&gt; theme.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The AI picked &lt;code&gt;stateDiagram-v2&lt;/code&gt; (the current syntax), used &lt;code&gt;[*]&lt;/code&gt; for entry and exit, and put transition labels after the colon. All things I'd otherwise look up.&lt;/p&gt;

&lt;p&gt;There's a subtler thing happening: the prompt described "from paid, the customer can cancel to refunded" — a side branch from the main happy path. The AI laid it out as a separate transition rather than nesting it inside a &lt;code&gt;state Paid { ... }&lt;/code&gt; block. That's a layout decision the model made for you. If you wanted the refund flow nested, you'd add "group Paid → Refunded into a Paid composite state" to the prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt 5 — Notification class hierarchy (class diagram)
&lt;/h2&gt;

&lt;p&gt;Class diagrams are the format devs hate most. The syntax is verbose, the cardinality / inheritance arrows are easy to mix up, and you write maybe two per year.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bd ai generate &lt;span class="s2"&gt;"class hierarchy for a polymorphic notification &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
system: base Notification with channel and deliver(), then &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
EmailNotification with htmlBody and fromAddress, SmsNotification &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
with shortMessage and senderId, PushNotification with deeplink &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
and iconUrl"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;classDiagram
  class Notification {
    +String channel
    +deliver()
  }
  class EmailNotification {
    +String htmlBody
    +String fromAddress
  }
  class SmsNotification {
    +String shortMessage
    +String senderId
  }
  class PushNotification {
    +String deeplink
    +String iconUrl
  }
  Notification &amp;lt;|-- EmailNotification
  Notification &amp;lt;|-- SmsNotification
  Notification &amp;lt;|-- PushNotification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwjzpag7sfc9le0fxltzs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwjzpag7sfc9le0fxltzs.png" alt="A class diagram showing a Notification base class with three subclasses: EmailNotification, SmsNotification, and PushNotification, each with their channel-specific fields" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Three-channel notification class hierarchy. Rendered with the &lt;code&gt;atelier&lt;/code&gt; theme.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;|--&lt;/code&gt; (empty triangle, hollow head, line) is the inheritance arrow. Reversed direction (&lt;code&gt;--|&amp;gt;&lt;/code&gt;) means the same relationship from the other end. Knowing that one glyph fluently is the difference between a 30-second class diagram and a 5-minute one. The AI knows it; you don't have to.&lt;/p&gt;

&lt;h2&gt;
  
  
  When NOT to use AI
&lt;/h2&gt;

&lt;p&gt;The prompt-to-diagram path is great for drafts. It's a worse fit for these cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The diagram already exists, you're refining it.&lt;/strong&gt; Editing five nodes by hand is faster than prompting "the same diagram but with X changed." Refinement is what the editor's source pane is for.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need precise layout.&lt;/strong&gt; AI controls the &lt;em&gt;content&lt;/em&gt; (nodes, edges, labels). It doesn't control left-vs-right ordering, column widths, where the diamond lands. If a stakeholder needs the "approve" branch on the right specifically, you'll be editing the source anyway.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The diagram encodes ground truth.&lt;/strong&gt; Database schemas pulled from &lt;code&gt;\dt&lt;/code&gt;, API call sequences pulled from logs, dependency graphs from your build system — pull these from the source of truth, don't have an AI guess. The AI is useful when &lt;em&gt;you're&lt;/em&gt; the source of truth and the friction is just getting it into Mermaid syntax.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You're learning Mermaid.&lt;/strong&gt; If your goal is to internalize the syntax for a diagram type you'll need monthly, hand-write the first five. After that, automation is fine. Skipping the learning round costs you forever.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The rule of thumb: use AI for "I know what I want and I don't want to look up the syntax." Don't use it for "I don't know what the diagram should show yet" or "this diagram needs to be load-bearing for an audit."&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Skip the docs lookup: Prompt to rendered diagram, end to end&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.beauty-diagram.com" rel="noopener noreferrer"&gt;Beauty Diagram&lt;/a&gt;'s AI panel generates Mermaid from plain English in the same editor where you pick a theme and export — no separate AI tool, no copy-paste round trip. The same pipeline runs from the CLI for scripted use. &lt;em&gt;(Disclosure: I work on it.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;→ Try it in the editor&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;The web flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the editor at &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;/editor&lt;/a&gt; and click the &lt;strong&gt;AI Generate&lt;/strong&gt; panel.&lt;/li&gt;
&lt;li&gt;Type your prompt. The model writes Mermaid into the source pane.&lt;/li&gt;
&lt;li&gt;Tweak the source if needed — rename a participant, reorder an entity, retitle an arrow.&lt;/li&gt;
&lt;li&gt;Pick a theme (&lt;code&gt;classic&lt;/code&gt;, &lt;code&gt;modern&lt;/code&gt;, &lt;code&gt;atlas&lt;/code&gt;, &lt;code&gt;blueprint&lt;/code&gt;, &lt;code&gt;memphis&lt;/code&gt;, &lt;code&gt;obsidian&lt;/code&gt;, &lt;code&gt;slate&lt;/code&gt;, &lt;code&gt;brutalist&lt;/code&gt;, or &lt;code&gt;atelier&lt;/code&gt;) and export SVG or PNG.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you'd rather script it from the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Print Mermaid to stdout&lt;/span&gt;
npx @beauty-diagram/cli ai generate &lt;span class="s2"&gt;"user signup with email verification"&lt;/span&gt;

&lt;span class="c"&gt;# Pipe straight into the renderer with a theme&lt;/span&gt;
npx @beauty-diagram/cli ai generate &lt;span class="s2"&gt;"user signup with email verification"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | npx @beauty-diagram/cli beautify - &lt;span class="nt"&gt;--theme&lt;/span&gt; modern &lt;span class="nt"&gt;--out&lt;/span&gt; signup.svg

&lt;span class="c"&gt;# Or save the source and the SVG together&lt;/span&gt;
npx @beauty-diagram/cli ai generate &lt;span class="s2"&gt;"user signup with email verification"&lt;/span&gt; &lt;span class="nt"&gt;--out&lt;/span&gt; signup.mmd
npx @beauty-diagram/cli beautify signup.mmd &lt;span class="nt"&gt;--theme&lt;/span&gt; modern &lt;span class="nt"&gt;--out&lt;/span&gt; signup.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;bd ai generate&lt;/code&gt; is paid-plan only — &lt;code&gt;bd auth login&lt;/code&gt; saves a key locally, or set &lt;code&gt;BEAUTY_DIAGRAM_API_KEY&lt;/code&gt; in CI. The renderer half (&lt;code&gt;bd beautify&lt;/code&gt;, &lt;code&gt;bd export&lt;/code&gt;) works anonymously if you only need rendering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;The three takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use AI for the diagram types you don't write often.&lt;/strong&gt; Sequence, ER, class, state — anything where you'd otherwise re-read the docs. Flowcharts you already write fluently; skip the AI if you don't need the speed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat the output as a draft.&lt;/strong&gt; Rename, reorder, retheme. The prompt got you past the syntax wall; you still own the diagram.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two surfaces, one engine.&lt;/strong&gt; Editor for iteration, CLI for scripts. The CLI's &lt;code&gt;bd ai generate | bd beautify -&lt;/code&gt; pipe is the fastest "prompt to SVG on disk" path.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this was useful, drop a ❤️ and follow — I'm posting weekly on diagrams, docs, and developer ergonomics. Next week: &lt;strong&gt;Beautify Every Diagram in Your Markdown Docs with One Command&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What's the diagram type you re-read the docs for every time? Sequence? State? ER? Drop it in the comments — I'm building a list of "which Mermaid types people forget most" and the answers so far are surprising.&lt;/p&gt;

</description>
      <category>mermaid</category>
      <category>ai</category>
      <category>cli</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Mermaid vs PlantUML in 2026: Which to Pick for Engineering Docs</title>
      <dc:creator>Levi Liu</dc:creator>
      <pubDate>Tue, 02 Jun 2026 16:15:22 +0000</pubDate>
      <link>https://dev.to/levi_liu/mermaid-vs-plantuml-in-2026-which-to-pick-for-engineering-docs-59dm</link>
      <guid>https://dev.to/levi_liu/mermaid-vs-plantuml-in-2026-which-to-pick-for-engineering-docs-59dm</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
Mermaid won the README and the markdown ecosystem; PlantUML won the engineering whiteboard and the IDE. In 2026 they're still the two serious "diagram as code" formats, and which one you should pick depends on where the diagram lives more than what it shows. This post compares them on syntax, layout, diagram coverage, and ecosystem, ending with a decision rule you can apply in 60 seconds. Both render through the same &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;editor&lt;/a&gt; if you want to try them side by side without installing anything.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The honest framing
&lt;/h2&gt;

&lt;p&gt;I've shipped engineering docs with both. Every six months someone on the team asks "should we standardise on Mermaid or PlantUML?" and every six months the answer is "it depends on where the diagram lives."&lt;/p&gt;

&lt;p&gt;That answer used to be a cop-out. In 2026 it's the truth. The two formats have converged on the same problem — render diagrams from plain text — and diverged on everything around it: who writes them, where they render, what they look like, and how much patience they expect from you.&lt;/p&gt;

&lt;p&gt;This article is the side-by-side I wish someone had handed me three years ago.&lt;/p&gt;

&lt;h2&gt;
  
  
  At a glance
&lt;/h2&gt;

&lt;p&gt;The table you came here for:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Mermaid&lt;/th&gt;
&lt;th&gt;PlantUML&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Native rendering on GitHub&lt;/td&gt;
&lt;td&gt;✅ since 2022&lt;/td&gt;
&lt;td&gt;❌ (proxied images only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Native rendering on Notion&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Native rendering on GitLab&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IDE / editor extensions&lt;/td&gt;
&lt;td&gt;Broad (VS Code, JetBrains, Obsidian)&lt;/td&gt;
&lt;td&gt;Broad, with deeper JetBrains roots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Layout engine&lt;/td&gt;
&lt;td&gt;Dagre (flowcharts), ELK opt-in&lt;/td&gt;
&lt;td&gt;Graphviz (&lt;code&gt;dot&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supported diagram types&lt;/td&gt;
&lt;td&gt;~16&lt;/td&gt;
&lt;td&gt;~20+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Syntax style&lt;/td&gt;
&lt;td&gt;Markdown-adjacent&lt;/td&gt;
&lt;td&gt;Annotation-heavy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server-side renderer&lt;/td&gt;
&lt;td&gt;Headless Chromium&lt;/td&gt;
&lt;td&gt;Java + Graphviz&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best at&lt;/td&gt;
&lt;td&gt;Flowcharts, sequence, journey&lt;/td&gt;
&lt;td&gt;Class, component, deployment, ERD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Worst at&lt;/td&gt;
&lt;td&gt;Dense ERDs, large class diagrams&lt;/td&gt;
&lt;td&gt;Anything that needs to live on GitHub&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The rest of this post is the detail under each row.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 1 — Syntax ergonomics
&lt;/h2&gt;

&lt;p&gt;The same flow, written two ways. Pick which one reads more naturally to you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mermaid:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
  A[Client] --&amp;gt; B{Token valid?}
  B --&amp;gt;|Yes| C[Fetch user]
  B --&amp;gt;|No| D[Redirect to login]
  C --&amp;gt; E[Return 200]
  D --&amp;gt; F[Return 302]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;PlantUML:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@startuml
start
:Client;
if (Token valid?) then (yes)
  :Fetch user;
  :Return 200;
else (no)
  :Redirect to login;
  :Return 302;
endif
@enduml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mermaid's syntax leans on &lt;strong&gt;nodes and edges as the primitive&lt;/strong&gt;. You say "A points to B with this label" and the layout follows. It reads like a constraint list.&lt;/p&gt;

&lt;p&gt;PlantUML's syntax leans on &lt;strong&gt;statements as the primitive&lt;/strong&gt;. You say "do this, then this, with this branch" and the layout follows. It reads like pseudocode.&lt;/p&gt;

&lt;p&gt;For people who think in flow ("first this happens, then this"), PlantUML's &lt;code&gt;start/if/endif&lt;/code&gt; is intuitive. For people who think in graphs ("these are the nodes, these are the edges"), Mermaid is the lower-friction path.&lt;/p&gt;

&lt;p&gt;There's no objectively-better here. Pick the one that matches how your team already whiteboards.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8dc8emezazdfx4gbkm5j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8dc8emezazdfx4gbkm5j.png" alt="Same auth flow rendered from Mermaid source" width="800" height="667"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Same auth flow, Mermaid source, rendered into a finished SVG.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn17ra5im0gkddqvfo8x4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn17ra5im0gkddqvfo8x4.png" alt="Same auth flow rendered from PlantUML source" width="800" height="667"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Same flow expressed in PlantUML — different syntax, same end shape.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 2 — Layout quality
&lt;/h2&gt;

&lt;p&gt;Layout is where the two diverge the most, and it's the thing nobody talks about until they've shipped a dozen diagrams and realised one of the formats keeps making nodes overlap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mermaid uses Dagre&lt;/strong&gt; by default. Dagre is a hierarchical layout algorithm — fast, deterministic, and great on flow charts with 5 to 30 nodes. Past that it starts producing the visual you've seen on a thousand READMEs: tall, narrow columns with edges crossing in ways no human would draw.&lt;/p&gt;

&lt;p&gt;Mermaid has an &lt;code&gt;elk&lt;/code&gt; opt-in (Eclipse Layout Kernel) that's much better at dense graphs. As of 2026 it's still flagged as experimental in most distributions, but it's stable enough to use in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PlantUML uses Graphviz&lt;/strong&gt; (the &lt;code&gt;dot&lt;/code&gt; engine), which has been the gold standard for hierarchical graph layout for 30 years. The output reflects that — PlantUML diagrams routinely look right out of the box, especially as the graph grows past 20 nodes.&lt;/p&gt;

&lt;p&gt;For a 6-node flow chart, both produce something readable. For a 60-node class diagram, PlantUML wins by a noticeable margin.&lt;/p&gt;

&lt;p&gt;The catch: Graphviz is a native binary. Running PlantUML in a CI job or a serverless function means shipping a Java + Graphviz runtime. Mermaid is JavaScript end-to-end, which is the trade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 3 — Supported diagram types
&lt;/h2&gt;

&lt;p&gt;Both cover the basics; PlantUML covers more obscure ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mermaid (2026, native pack):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flowchart&lt;/li&gt;
&lt;li&gt;Sequence diagram&lt;/li&gt;
&lt;li&gt;Class diagram&lt;/li&gt;
&lt;li&gt;State diagram&lt;/li&gt;
&lt;li&gt;ER diagram&lt;/li&gt;
&lt;li&gt;Gantt&lt;/li&gt;
&lt;li&gt;Pie&lt;/li&gt;
&lt;li&gt;User journey&lt;/li&gt;
&lt;li&gt;Quadrant chart&lt;/li&gt;
&lt;li&gt;XY chart&lt;/li&gt;
&lt;li&gt;Mindmap&lt;/li&gt;
&lt;li&gt;Timeline&lt;/li&gt;
&lt;li&gt;Sankey&lt;/li&gt;
&lt;li&gt;Block diagram&lt;/li&gt;
&lt;li&gt;Git graph&lt;/li&gt;
&lt;li&gt;C4 (experimental)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;PlantUML (mature set):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All of the above, plus:&lt;/li&gt;
&lt;li&gt;Component diagram&lt;/li&gt;
&lt;li&gt;Deployment diagram&lt;/li&gt;
&lt;li&gt;Activity diagram (legacy + beta)&lt;/li&gt;
&lt;li&gt;Use case&lt;/li&gt;
&lt;li&gt;Object diagram&lt;/li&gt;
&lt;li&gt;Network diagram (&lt;code&gt;nwdiag&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Wireframe (Salt UI mockup)&lt;/li&gt;
&lt;li&gt;Archimate&lt;/li&gt;
&lt;li&gt;BPMN-like activity flows&lt;/li&gt;
&lt;li&gt;Bytefield diagrams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're writing a software architecture doc that needs &lt;strong&gt;deployment diagrams or component diagrams&lt;/strong&gt; — the boxes-inside-boxes-with-interfaces pattern — PlantUML's coverage is meaningfully wider. Mermaid's &lt;code&gt;block&lt;/code&gt; diagram type covers a chunk of this, but it's not at parity.&lt;/p&gt;

&lt;p&gt;If you're writing a feature spec with &lt;strong&gt;flowcharts, sequence diagrams, and ER diagrams&lt;/strong&gt; — the 80% case for product engineering — both are fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 4 — Where it renders without help
&lt;/h2&gt;

&lt;p&gt;This is the single biggest practical difference, and the reason the answer in 2026 is "it depends on where the diagram lives".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mermaid renders natively on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub READMEs and markdown files (since 2022)&lt;/li&gt;
&lt;li&gt;GitLab&lt;/li&gt;
&lt;li&gt;Notion code blocks&lt;/li&gt;
&lt;li&gt;VS Code markdown preview&lt;/li&gt;
&lt;li&gt;Obsidian&lt;/li&gt;
&lt;li&gt;Bitbucket Cloud&lt;/li&gt;
&lt;li&gt;Most static site generators with a plugin (Docusaurus, VitePress, MkDocs Material, Astro)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;PlantUML renders natively on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitLab (snippets + wiki)&lt;/li&gt;
&lt;li&gt;JetBrains IDEs (with the official plugin)&lt;/li&gt;
&lt;li&gt;Confluence (with a plugin)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everywhere else, PlantUML rendering means either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pre-rendering to SVG/PNG and committing the image, or&lt;/li&gt;
&lt;li&gt;Pointing at a public PlantUML server (&lt;code&gt;www.plantuml.com/plantuml/svg/&amp;lt;encoded&amp;gt;&lt;/code&gt;) and accepting that your diagram source is encoded into a third-party URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For a GitHub README in 2026, Mermaid is the only format that renders inline without a build step. That's not a small thing — it's the entire reason Mermaid has more momentum.&lt;/p&gt;

&lt;p&gt;For an internal Confluence-driven engineering org, PlantUML's class / component / deployment coverage and Graphviz layout makes it the better default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 5 — Ecosystem and tooling
&lt;/h2&gt;

&lt;p&gt;Both ecosystems are healthy. They optimise for different surfaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mermaid:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintained by a foundation; weekly releases&lt;/li&gt;
&lt;li&gt;Live editor at &lt;code&gt;mermaid.live&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Official CLI: &lt;code&gt;@mermaid-js/mermaid-cli&lt;/code&gt; (uses Puppeteer under the hood)&lt;/li&gt;
&lt;li&gt;VS Code extension by the maintainers&lt;/li&gt;
&lt;li&gt;Obsidian native support&lt;/li&gt;
&lt;li&gt;AI tooling generates Mermaid by default — most LLMs output Mermaid when asked for a diagram in markdown&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;PlantUML:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintained primarily by Arnaud Roques and a small team; releases are slower but steady&lt;/li&gt;
&lt;li&gt;Live editor at &lt;code&gt;www.plantuml.com/plantuml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Official tool: &lt;code&gt;plantuml.jar&lt;/code&gt; (Java)&lt;/li&gt;
&lt;li&gt;JetBrains plugin is best-in-class for the JVM crowd&lt;/li&gt;
&lt;li&gt;Confluence integration is a paid plugin but widely deployed&lt;/li&gt;
&lt;li&gt;AI tooling support is improving but still trails Mermaid&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's a quieter consequence here. When you ask an LLM for "a diagram of X", you almost always get Mermaid back. That's mostly habit and training-set bias, not a quality call — but it does mean that if your team is leaning on AI-assisted doc writing, Mermaid will show up in your repo whether you picked it or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 6 — Learning curve
&lt;/h2&gt;

&lt;p&gt;The bottom 20% of each language takes about an hour. The remaining 80% is what differs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mermaid&lt;/strong&gt; has a flat learning curve — the syntax is markdown-adjacent and most people write a working flowchart on their first try. The wall comes when you want to customise — &lt;code&gt;themeVariables&lt;/code&gt;, &lt;code&gt;init&lt;/code&gt; directives, &lt;code&gt;classDef&lt;/code&gt;, link styling — because each diagram type has its own subset of the customisation surface, and the documentation is scattered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PlantUML&lt;/strong&gt; has a steeper start — &lt;code&gt;@startuml&lt;/code&gt; / &lt;code&gt;@enduml&lt;/code&gt;, statement-based syntax, &lt;code&gt;skinparam&lt;/code&gt; overrides — but a flatter middle, because once you've learned &lt;code&gt;skinparam&lt;/code&gt; you've learned the customisation surface for every diagram type. The wall comes later, around legacy syntax (the original &lt;code&gt;activity&lt;/code&gt; grammar vs the newer &lt;code&gt;start/stop&lt;/code&gt; beta).&lt;/p&gt;

&lt;p&gt;For a team that ships occasional diagrams, Mermaid's flat start wins. For a team where someone "owns" the diagram system and is going to push it to its limits, PlantUML's consistency wins.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision rule
&lt;/h2&gt;

&lt;p&gt;Three questions, in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Does the diagram need to render on GitHub or in a markdown file consumed by tools you don't control?&lt;/strong&gt; → Mermaid. Stop here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does it need to be a deployment, component, or detailed class diagram with 30+ nodes?&lt;/strong&gt; → PlantUML. Stop here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anything else?&lt;/strong&gt; → Mermaid for the lower install footprint and broader AI tooling; PlantUML if your team is already on JetBrains + Confluence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqjikzly4163zgz8tzd7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqjikzly4163zgz8tzd7.png" alt="Decision rule visualised as a three-question flow" width="800" height="667"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The 60-second decision rule.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most engineering teams in 2026 end up using &lt;strong&gt;Mermaid for repo-level docs and PlantUML for architecture documents that live in Confluence or a wiki.&lt;/strong&gt; That's not a compromise — it's the right answer. The cost of standardising on one format and forcing the wrong fit is higher than the cost of two file extensions in your repo.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Both formats, one editor: Don't pick — render both&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.beauty-diagram.com" rel="noopener noreferrer"&gt;Beauty Diagram&lt;/a&gt; parses Mermaid, PlantUML, and draw.io. Paste either format, pick from 9 production themes, export SVG or PNG. Useful when your docs repo has both formats and you want them to look consistent. &lt;em&gt;(Disclosure: I work on it.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;→ Try the editor&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;The web flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Paste&lt;/strong&gt; the source — Mermaid or PlantUML — into the editor at &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;/editor&lt;/a&gt;. The format is auto-detected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick a theme&lt;/strong&gt;. The same nine themes (&lt;code&gt;classic&lt;/code&gt;, &lt;code&gt;modern&lt;/code&gt;, &lt;code&gt;atlas&lt;/code&gt;, &lt;code&gt;blueprint&lt;/code&gt;, &lt;code&gt;memphis&lt;/code&gt;, &lt;code&gt;obsidian&lt;/code&gt;, &lt;code&gt;slate&lt;/code&gt;, &lt;code&gt;brutalist&lt;/code&gt;, &lt;code&gt;atelier&lt;/code&gt;) apply to both formats, so a doc with a mix of Mermaid and PlantUML diagrams renders consistently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export&lt;/strong&gt; SVG or PNG, or use &lt;strong&gt;Share&lt;/strong&gt; to get a hot-linkable URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're scripting this from CI — say, beautifying every diagram in your docs repo on each release — the same pipeline runs from a CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Works on both Mermaid and PlantUML files&lt;/span&gt;
npx @beauty-diagram/cli beautify auth.mmd &lt;span class="nt"&gt;--theme&lt;/span&gt; atlas &lt;span class="nt"&gt;--out&lt;/span&gt; auth.svg
npx @beauty-diagram/cli beautify components.puml &lt;span class="nt"&gt;--theme&lt;/span&gt; atlas &lt;span class="nt"&gt;--out&lt;/span&gt; components.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;bd themes&lt;/code&gt; lists the available themes. There's no per-property style override — the theme is the choice; you pick a different one if you don't like what you see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;The 60-second version:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mermaid wins&lt;/strong&gt; if the diagram lives in a README, a markdown file, a Notion page, or anything you don't fully control. It also wins if you're heavy on AI-assisted doc writing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PlantUML wins&lt;/strong&gt; if the diagram is a deployment / component / detailed class diagram, or if your team is centred on JetBrains + Confluence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Both is fine.&lt;/strong&gt; Pick the format per-diagram, not per-org.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this was useful, drop a ❤️ and follow — I'm posting weekly on diagrams, docs, and developer ergonomics. Next week: &lt;strong&gt;Generate Mermaid from plain English with AI — a CLI walkthrough&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Which one is your team standardised on, and did the decision survive the second year? Drop a note in the comments — I'm collecting the regret-or-validation stories.&lt;/p&gt;

</description>
      <category>mermaid</category>
      <category>plantuml</category>
      <category>opensource</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Embed Mermaid in Notion: The 4 Working Approaches in 2026</title>
      <dc:creator>Levi Liu</dc:creator>
      <pubDate>Tue, 26 May 2026 10:38:23 +0000</pubDate>
      <link>https://dev.to/levi_liu/embed-mermaid-in-notion-the-4-working-approaches-in-2026-257f</link>
      <guid>https://dev.to/levi_liu/embed-mermaid-in-notion-the-4-working-approaches-in-2026-257f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
Notion has native Mermaid in code blocks now, but the default look is the same pastel render you've seen everywhere, and there's no theme override. This post walks through the four approaches that actually work in 2026 — native code block, static image upload, public hot-linkable image, and live-updating embed — with a comparison table at the end so you can pick by trade-off. There's a &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;shortcut&lt;/a&gt; at the 70% mark if you'd rather skip the maintenance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why this article exists
&lt;/h2&gt;

&lt;p&gt;Two years ago, "embed Mermaid in Notion" was a search query that returned twenty Stack Overflow threads and zero working answers. Then Notion shipped native &lt;code&gt;mermaid&lt;/code&gt; code-block rendering, and the question went quiet.&lt;/p&gt;

&lt;p&gt;But the question didn't go away — it shifted. The native renderer works, but it gives you exactly one look: Mermaid's default theme, no overrides, no &lt;code&gt;themeVariables&lt;/code&gt; honored. The moment you want your team's Notion docs to feel like a finished product instead of a hackathon scratchpad, you're back to needing a workaround.&lt;/p&gt;

&lt;p&gt;There are four of them. Each makes a different trade between live-updating, aesthetic control, and how much pipeline you're willing to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four approaches at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Live updates&lt;/th&gt;
&lt;th&gt;Theme control&lt;/th&gt;
&lt;th&gt;Maintenance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. Native &lt;code&gt;mermaid&lt;/code&gt; code block&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Static image upload&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Manual re-upload&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Public hot-linkable image&lt;/td&gt;
&lt;td&gt;✅*&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Host the image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4. Live embed via &lt;code&gt;/embed&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Host the endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;* Live updates only if the source URL serves a fresh render each time.&lt;/p&gt;

&lt;p&gt;The rest of this post is just the details under each row.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 1: Native &lt;code&gt;mermaid&lt;/code&gt; code block
&lt;/h2&gt;

&lt;p&gt;The cheapest path. Type &lt;code&gt;/code&lt;/code&gt;, set the language to &lt;strong&gt;Mermaid&lt;/strong&gt;, paste your source.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
  A[Client] --&amp;gt; B{Auth?}
  B --&amp;gt;|Yes| C[API]
  B --&amp;gt;|No| D[Login]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notion renders it live. You can edit the source, the diagram re-renders. Free, zero pipeline.&lt;/p&gt;

&lt;p&gt;What you give up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No theme override.&lt;/strong&gt; The &lt;code&gt;%%{init: {...}}%%&lt;/code&gt; directive is silently stripped in Notion's renderer. You get default Mermaid pastels whether you want them or not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; for dark mode.&lt;/strong&gt; Notion's dark/light switch doesn't tell Mermaid anything; the diagram stays one fixed palette.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No PDF export fidelity.&lt;/strong&gt; When you export the Notion page to PDF, the Mermaid block renders as a raster snapshot, often at a lower resolution than the page expects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use this for: internal scratch docs, RFCs, anything where "the diagram exists" is the bar.&lt;/p&gt;

&lt;p&gt;Don't use this for: public-facing docs, customer-shared Notion pages, anything you'd want to look intentional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 2: Static image upload
&lt;/h2&gt;

&lt;p&gt;Render the diagram to SVG or PNG offline, then drag the file into Notion. It becomes an Image block; Notion hosts it on its own CDN.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Official Mermaid CLI&lt;/span&gt;
npx @mermaid-js/mermaid-cli &lt;span class="nt"&gt;-i&lt;/span&gt; flow.mmd &lt;span class="nt"&gt;-o&lt;/span&gt; flow.svg &lt;span class="nt"&gt;-t&lt;/span&gt; base
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drag &lt;code&gt;flow.svg&lt;/code&gt; into the Notion page. Done.&lt;/p&gt;

&lt;p&gt;Pros: full theme control (you're rendering it yourself), works in PDF export, looks identical light and dark.&lt;/p&gt;

&lt;p&gt;Cons: &lt;strong&gt;no live updates.&lt;/strong&gt; Edit the Mermaid source, you re-render the file, you re-upload it. For a doc with five diagrams that change quarterly, this is fine. For a system architecture page that drifts weekly, it's a paper cut.&lt;/p&gt;

&lt;p&gt;A subtle gotcha: Notion &lt;strong&gt;strips SVG &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags and external font references&lt;/strong&gt; on upload. If your SVG depends on a webfont link in &lt;code&gt;&amp;lt;defs&amp;gt;&lt;/code&gt;, the text falls back to Notion's default font. Inline the font with &lt;code&gt;font-family: -apple-system, system-ui, sans-serif&lt;/code&gt; to avoid the mismatch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 3: Public hot-linkable image
&lt;/h2&gt;

&lt;p&gt;Host the SVG somewhere public, then in Notion: &lt;code&gt;/image&lt;/code&gt; → &lt;strong&gt;Embed link&lt;/strong&gt; → paste the URL. Notion fetches it on every page load.&lt;/p&gt;

&lt;p&gt;This is the sweet spot for repos that already commit their diagrams as SVG. The pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Render the diagram into your repo: &lt;code&gt;diagrams/auth-flow.svg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Commit and push.&lt;/li&gt;
&lt;li&gt;In Notion, embed: &lt;code&gt;https://github.com/&amp;lt;org&amp;gt;/&amp;lt;repo&amp;gt;/raw/main/diagrams/auth-flow.svg&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Notion will fetch the URL each time the page loads. Push a new SVG to &lt;code&gt;main&lt;/code&gt;, the embed updates within a few minutes (GitHub's raw CDN has a short TTL).&lt;/p&gt;

&lt;p&gt;The catch: GitHub's &lt;code&gt;raw.githubusercontent.com&lt;/code&gt; serves with &lt;code&gt;Content-Type: text/plain&lt;/code&gt;, which some browsers refuse to render as an image. The reliable trick is to route through &lt;code&gt;https://github.com/&amp;lt;org&amp;gt;/&amp;lt;repo&amp;gt;/raw/main/...&lt;/code&gt; (no &lt;code&gt;raw.&lt;/code&gt; prefix), which redirects to a properly typed CDN response. Notion handles this redirect correctly.&lt;/p&gt;

&lt;p&gt;Other hosts work too — Cloudflare R2, S3 with a public bucket, any static CDN. The constraint is just: serve &lt;code&gt;image/svg+xml&lt;/code&gt;, allow Notion's user-agent, and don't gate behind auth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 4: Live embed via &lt;code&gt;/embed&lt;/code&gt; + hosted SVG endpoint
&lt;/h2&gt;

&lt;p&gt;The most flexible — and the most pipeline. Use Notion's &lt;code&gt;/embed&lt;/code&gt; block (which accepts any URL) to point at an endpoint that renders the Mermaid source on demand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/embed → https://your-domain.com/render?source=&amp;lt;encoded-mermaid&amp;gt;&amp;amp;theme=atlas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The endpoint does what Mermaid CLI does, but server-side, and returns &lt;code&gt;image/svg+xml&lt;/code&gt;. You can pass theme parameters in the query string, regenerate on every request, and the diagram in Notion always reflects whatever the endpoint serves right now.&lt;/p&gt;

&lt;p&gt;A barebones version in 50 lines of Node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@mermaid-js/mermaid-cli&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs/promises&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/render&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tmpIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`/tmp/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;.mmd`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tmpOut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tmpIn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.mmd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tmpIn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tmpIn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tmpOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;puppeteerConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--no-sandbox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tmpOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image/svg+xml&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the "I want full control" path. You're now running a renderer. That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A box (Lambda, Cloud Run, a Fly machine) running Chromium for Puppeteer&lt;/li&gt;
&lt;li&gt;A cache layer so identical sources don't re-render on every Notion poll&lt;/li&gt;
&lt;li&gt;A timeout policy so a malformed source doesn't hang&lt;/li&gt;
&lt;li&gt;Some auth or rate limiting so the endpoint doesn't become someone else's free render farm&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a team that already has infra, the 80% solution above is a weekend project. For a solo dev, it's the moment you ask whether the time is worth it.&lt;/p&gt;

&lt;h2&gt;
  
  
  When DIY stops being worth it
&lt;/h2&gt;

&lt;p&gt;Three signals it's time to stop hand-rolling the Notion pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You have more than ~10 diagrams across your Notion workspace and you're losing track of which ones are stale.&lt;/li&gt;
&lt;li&gt;You want a theme that matches your company's docs site, not Mermaid's defaults.&lt;/li&gt;
&lt;li&gt;The team's non-engineers want to make and edit diagrams without learning Mermaid or your render endpoint.&lt;/li&gt;
&lt;/ol&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The shortcut: Paste, pick a theme, embed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.beauty-diagram.com" rel="noopener noreferrer"&gt;Beauty Diagram&lt;/a&gt; is a web editor for Mermaid, PlantUML, and draw.io. Paste your source, pick from 9 production themes, get a hot-linkable URL that updates when you edit. Drop the URL into Notion's &lt;code&gt;/embed&lt;/code&gt; block and it stays live. &lt;em&gt;(Disclosure: I work on it.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;→ Try the editor&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;The web flow for Notion specifically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Paste&lt;/strong&gt; your Mermaid source into the &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;editor&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick a theme&lt;/strong&gt; from nine: &lt;code&gt;classic&lt;/code&gt;, &lt;code&gt;modern&lt;/code&gt;, &lt;code&gt;atlas&lt;/code&gt;, &lt;code&gt;blueprint&lt;/code&gt;, &lt;code&gt;memphis&lt;/code&gt;, &lt;code&gt;obsidian&lt;/code&gt;, &lt;code&gt;slate&lt;/code&gt;, &lt;code&gt;brutalist&lt;/code&gt;, &lt;code&gt;atelier&lt;/code&gt;. Each is a complete design language — palette, typography, edge style, node treatment — tuned so the embed reads as a finished asset.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save &amp;amp; Share&lt;/strong&gt; — generates a public URL with a 12-char token.&lt;/li&gt;
&lt;li&gt;In Notion, &lt;code&gt;/embed&lt;/code&gt; and paste the share URL's &lt;code&gt;.svg&lt;/code&gt; form, e.g. &lt;code&gt;https://api.beauty-diagram.com/v1/share/&amp;lt;token&amp;gt;.svg&lt;/code&gt;. The embed re-fetches on each page load; if you edit the share, Notion shows the new version within ~5 minutes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you'd rather automate from a CLI — say, a CI job that regenerates every diagram in your repo on each release — the same render pipeline is one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Render and get a hot-linkable URL in one shot&lt;/span&gt;
npx @beauty-diagram/cli embed-url flow.mmd &lt;span class="nt"&gt;--theme&lt;/span&gt; atlas &lt;span class="nt"&gt;--share&lt;/span&gt;
&lt;span class="c"&gt;# → https://api.beauty-diagram.com/v1/share/&amp;lt;token&amp;gt;.svg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;bd embed-url --share&lt;/code&gt; saves the diagram first, then prints the share-resource SVG URL. Drop that URL directly into a Notion &lt;code&gt;/embed&lt;/code&gt; block, or any other surface that accepts an image URL. Re-running on the same file replaces the share contents in place, so the URL is stable and the embed picks up the update automatically.&lt;/p&gt;

&lt;p&gt;The CLI exposes the same nine themes (&lt;code&gt;bd themes&lt;/code&gt; lists them). It does not expose per-property style overrides — the philosophy is that the theme is the choice; you don't tune a theme, you pick a different one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Picking the right approach for your page
&lt;/h2&gt;

&lt;p&gt;A rough decision tree:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Throwaway internal doc?&lt;/strong&gt; Native code block. Five seconds, zero pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quarterly architecture review that gets exported to PDF?&lt;/strong&gt; Static SVG upload. Manual, but PDF-safe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diagrams that already live in your repo?&lt;/strong&gt; GitHub raw URL embed via &lt;code&gt;/image&lt;/code&gt;. Free, auto-updates on push.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer-facing Notion page, or a team doc that drifts weekly?&lt;/strong&gt; Live embed against a hosted endpoint. Either roll your own, or use a service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trap to avoid: picking the most powerful approach for every diagram. Native code blocks are fine when "the diagram exists" is the bar — don't over-engineer them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;The four approaches, recapped:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Native &lt;code&gt;mermaid&lt;/code&gt; code block&lt;/strong&gt; — free, live, but locked to Mermaid defaults.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static image upload&lt;/strong&gt; — full control, but no live updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public hot-linkable image&lt;/strong&gt; — live and themed, but you host the SVG.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live embed via &lt;code&gt;/embed&lt;/code&gt;&lt;/strong&gt; — full pipeline, full control, the most work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this was useful, drop a ❤️ and follow — I'm posting weekly on diagrams, docs, and developer ergonomics. Next week: &lt;strong&gt;Mermaid vs PlantUML in 2026 — which to pick for engineering docs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What's your team's Notion diagram setup — native blocks, static uploads, or something else? Drop a note in the comments; I'm collecting setups for a follow-up.&lt;/p&gt;

</description>
      <category>mermaid</category>
      <category>notion</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why Your GitHub README Diagrams Look Amateur (and the 4 Fixes That Take 10 Minutes)</title>
      <dc:creator>Levi Liu</dc:creator>
      <pubDate>Wed, 20 May 2026 10:41:08 +0000</pubDate>
      <link>https://dev.to/levi_liu/why-your-github-readme-diagrams-look-amateur-and-the-4-fixes-that-take-10-minutes-4a9c</link>
      <guid>https://dev.to/levi_liu/why-your-github-readme-diagrams-look-amateur-and-the-4-fixes-that-take-10-minutes-4a9c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
If your README diagrams look like every other open-source repo's, that's because they all use the same four defaults. Switching to &lt;code&gt;theme: 'base'&lt;/code&gt; plus tuning four properties takes under ten minutes and produces a diagram that looks intentional. This is a follow-up to last week's &lt;a href="https://www.beauty-diagram.com/blog/render-mermaid-as-svg" rel="noopener noreferrer"&gt;SVG rendering deep-dive&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The four defaults that ruin your diagrams
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pastel pink/blue palette&lt;/strong&gt; — the &lt;code&gt;default&lt;/code&gt; theme is from a 2014 Bootstrap-era moodboard. It signals "I copy-pasted from the docs."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Curved edges (&lt;code&gt;basis&lt;/code&gt;)&lt;/strong&gt; — works for organic flows, terrible for technical diagrams. Lines that should be crisp end up wavy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default font&lt;/strong&gt; — varies wildly by viewer. Looks fine in the GitHub editor preview, looks like Times New Roman in your CI artifact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hardcoded background&lt;/strong&gt; — light theme on a dark page, or vice versa. The diagram becomes a rectangle.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each takes one config change to fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix 1: Switch to base theme
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;%%{init: {'theme':'base'}}%%
flowchart LR
  A --&amp;gt; B --&amp;gt; C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;base&lt;/code&gt; is the only theme that exposes &lt;code&gt;themeVariables&lt;/code&gt; for full control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix 2: Set six theme variables
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;%%&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;init:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;'theme':'base'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;'themeVariables':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;'primaryColor':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'#&lt;/span&gt;&lt;span class="mi"&gt;1e293&lt;/span&gt;&lt;span class="err"&gt;b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;'primaryTextColor':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'#f&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="err"&gt;fafc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;'primaryBorderColor':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'#&lt;/span&gt;&lt;span class="mi"&gt;475569&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;'lineColor':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'#&lt;/span&gt;&lt;span class="mi"&gt;94&lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;b&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;'fontFamily':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'system-ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;sans-serif'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;'fontSize':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="err"&gt;px'&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="err"&gt;%%&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Six variables. That's the entire customization surface you actually need. Mermaid exposes around fifty in total, but the ones above cover 90% of the visual identity of a diagram. Ignore the rest unless you have a specific reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix 3: Linear edges
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;%%&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;init:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;'flowchart':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;'curve':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'linear'&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="err"&gt;%%&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For hierarchies, use &lt;code&gt;step&lt;/code&gt;. For organic flows, keep &lt;code&gt;basis&lt;/code&gt;. For everything else, &lt;code&gt;linear&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix 4: Light/dark adaptive embed
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(prefers-color-scheme: dark)"&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"./diagrams/auth-flow-dark.svg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Auth flow"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./diagrams/auth-flow-light.svg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub READMEs respect &lt;code&gt;prefers-color-scheme&lt;/code&gt;. Ship two SVGs and let GitHub pick.&lt;/p&gt;

&lt;p&gt;A small but important caveat: this only works for &lt;strong&gt;pre-rendered SVGs&lt;/strong&gt; that you commit to the repo. Inline &lt;code&gt;mermaid&lt;/code&gt; code blocks in your README can't use &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; — they're rendered by GitHub's own Mermaid runtime at view time, with no hook for swapping based on theme. If you want adaptive diagrams in a README, you have to render to SVG first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting all four together
&lt;/h2&gt;

&lt;p&gt;Here's the minimum viable beautified README diagram, end to end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
config:
  theme: base
  themeVariables:
    primaryColor: '#1e293b'
    primaryTextColor: '#f8fafc'
    primaryBorderColor: '#475569'
    lineColor: '#94a3b8'
    fontFamily: 'system-ui, sans-serif'
    fontSize: '14px'
  flowchart:
    curve: linear
---
flowchart LR
  A[Client] --&amp;gt; B{Auth?}
  B --&amp;gt;|Yes| C[API]
  B --&amp;gt;|No| D[Login]
  C --&amp;gt; E[(Database)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontmatter form (&lt;code&gt;---\nconfig:\n  ...&lt;/code&gt;) is Mermaid v11's preferred syntax. The older &lt;code&gt;%%{init: {...}}%%&lt;/code&gt; directive still works and is what you'll see in most blog posts — pick whichever your renderer is happy with.&lt;/p&gt;

&lt;h2&gt;
  
  
  When DIY stops being worth the time
&lt;/h2&gt;

&lt;p&gt;Everything above works. I've shipped this exact pipeline.&lt;/p&gt;

&lt;p&gt;But the moment you have more than a handful of diagrams, or you want a different look for slides vs. docs vs. PRs, you're maintaining a config file. And every new contributor to the repo needs to know about it. That's where I personally tap out.&lt;/p&gt;

&lt;p&gt;Three signals it's time to graduate from hand-tuned themes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You're copy-pasting the same &lt;code&gt;themeVariables&lt;/code&gt; block across multiple repos.&lt;/li&gt;
&lt;li&gt;You want a different look for a slide deck than for the README, but the diagram source stays the same.&lt;/li&gt;
&lt;li&gt;Someone non-technical on the team needs to make a diagram and you don't want to teach them YAML frontmatter.&lt;/li&gt;
&lt;/ol&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The shortcut: Paste, pick a theme, export&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.beauty-diagram.com" rel="noopener noreferrer"&gt;Beauty Diagram&lt;/a&gt; is a web editor for Mermaid, PlantUML, and draw.io. Paste your source, pick from 9 production themes, export SVG or PNG. No &lt;code&gt;themeVariables&lt;/code&gt; to maintain. &lt;em&gt;(Disclosure: I work on it.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;→ Open the editor&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;The fastest path is the &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;web editor&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Paste&lt;/strong&gt; your Mermaid source on the left.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick a theme&lt;/strong&gt; from nine: &lt;code&gt;classic&lt;/code&gt;, &lt;code&gt;modern&lt;/code&gt;, &lt;code&gt;atlas&lt;/code&gt;, &lt;code&gt;blueprint&lt;/code&gt;, &lt;code&gt;memphis&lt;/code&gt;, &lt;code&gt;obsidian&lt;/code&gt;, &lt;code&gt;slate&lt;/code&gt;, &lt;code&gt;brutalist&lt;/code&gt;, &lt;code&gt;atelier&lt;/code&gt;. Each one is a complete design language — palette, typography, edge style, node treatment — not just a colour swap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export&lt;/strong&gt; SVG (vector for repos) or PNG (&lt;code&gt;standard&lt;/code&gt; / &lt;code&gt;high&lt;/code&gt; / &lt;code&gt;max&lt;/code&gt; quality for slides).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share&lt;/strong&gt; to get a public hot-linkable URL that updates when the source is edited — drop it into Notion or Linear without re-uploading.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The same renderer is also a CLI if you'd rather automate the README pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Render once, ship to your repo&lt;/span&gt;
npx @beauty-diagram/cli beautify flow.mmd &lt;span class="nt"&gt;--theme&lt;/span&gt; modern &lt;span class="nt"&gt;--out&lt;/span&gt; flow.svg

&lt;span class="c"&gt;# Or render light + dark in one go for the &amp;lt;picture&amp;gt; embed&lt;/span&gt;
npx @beauty-diagram/cli beautify flow.mmd &lt;span class="nt"&gt;--theme&lt;/span&gt; modern   &lt;span class="nt"&gt;--out&lt;/span&gt; flow-light.svg
npx @beauty-diagram/cli beautify flow.mmd &lt;span class="nt"&gt;--theme&lt;/span&gt; obsidian &lt;span class="nt"&gt;--out&lt;/span&gt; flow-dark.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI exposes the same nine themes (&lt;code&gt;bd themes&lt;/code&gt; lists them). It does not expose per-variable overrides — the philosophy is that the theme is the choice; you don't tune a theme, you pick a different one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;The README-diagram embarrassment problem is fixable in ten minutes. The four fixes, recapped:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;theme: 'base'&lt;/code&gt; — only theme that accepts overrides.&lt;/li&gt;
&lt;li&gt;Six &lt;code&gt;themeVariables&lt;/code&gt; — &lt;code&gt;primaryColor&lt;/code&gt;, &lt;code&gt;primaryTextColor&lt;/code&gt;, &lt;code&gt;primaryBorderColor&lt;/code&gt;, &lt;code&gt;lineColor&lt;/code&gt;, &lt;code&gt;fontFamily&lt;/code&gt;, &lt;code&gt;fontSize&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;flowchart.curve: linear&lt;/code&gt; — sharp edges for technical diagrams.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; + &lt;code&gt;prefers-color-scheme&lt;/code&gt; — adaptive light/dark, GitHub-native.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most repos haven't done it because nobody told them where to look. Now you know.&lt;/p&gt;

&lt;p&gt;If this was useful, drop a ❤️ and follow — I'm posting weekly on diagrams, docs, and developer ergonomics. Next week: &lt;strong&gt;how to embed Mermaid diagrams in Notion (the four working approaches in 2026)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What's the worst-looking diagram in a README you've actually opened a PR against? Drop a link in the comments — I'm collecting examples for a future post.&lt;/p&gt;

</description>
      <category>mermaid</category>
      <category>github</category>
      <category>opinion</category>
      <category>documentation</category>
    </item>
    <item>
      <title>How to Render Mermaid Diagrams as SVG (and Stop Looking Like Every Other README)</title>
      <dc:creator>Levi Liu</dc:creator>
      <pubDate>Sun, 10 May 2026 22:00:00 +0000</pubDate>
      <link>https://dev.to/levi_liu/how-to-render-mermaid-diagrams-as-svg-and-stop-looking-like-every-other-readme-1e10</link>
      <guid>https://dev.to/levi_liu/how-to-render-mermaid-diagrams-as-svg-and-stop-looking-like-every-other-readme-1e10</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
Mermaid renders to SVG natively — but the default output usually isn't what you want in a README, slide, or doc. This post walks through the official &lt;code&gt;mmdc&lt;/code&gt; CLI, the four theming knobs that actually matter, the three rendering pitfalls everyone hits (fonts, viewBox, dark mode), and the fastest path when you don't want to fight with config. There's a &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;live editor&lt;/a&gt; at the end if you want to skip ahead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The problem nobody talks about
&lt;/h2&gt;

&lt;p&gt;Mermaid is the de-facto "diagrams as code" choice in 2026 — GitHub, Notion, Obsidian, Docusaurus, GitLab, every static site generator worth its salt renders it natively.&lt;/p&gt;

&lt;p&gt;That's the good news.&lt;/p&gt;

&lt;p&gt;The bad news: 95% of Mermaid diagrams in the wild look exactly the same. Pastel pinks and blues, Comic-Sans-adjacent fonts, edges crossing nodes, arrowheads that don't quite point at anything. You've seen them. You've probably shipped some.&lt;/p&gt;

&lt;p&gt;It's not a Mermaid problem — it's a defaults problem. The renderer is optimized for "something showed up", not "this is presentable".&lt;/p&gt;

&lt;h2&gt;
  
  
  Why SVG and not PNG
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;SVG&lt;/th&gt;
&lt;th&gt;PNG&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scales without blur&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accessible (text selectable)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adapts to dark mode (&lt;code&gt;currentColor&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Searchable in your repo&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Approach 1: The official Mermaid CLI
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run without installing&lt;/span&gt;
npx @mermaid-js/mermaid-cli &lt;span class="nt"&gt;-i&lt;/span&gt; diagram.mmd &lt;span class="nt"&gt;-o&lt;/span&gt; diagram.svg

&lt;span class="c"&gt;# Or install globally&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @mermaid-js/mermaid-cli
mmdc &lt;span class="nt"&gt;-i&lt;/span&gt; diagram.mmd &lt;span class="nt"&gt;-o&lt;/span&gt; diagram.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The four theming knobs that actually matter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;theme&lt;/code&gt; (the cheapest win)
&lt;/h3&gt;

&lt;p&gt;Built-in Mermaid themes: &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;forest&lt;/code&gt;, &lt;code&gt;dark&lt;/code&gt;, &lt;code&gt;neutral&lt;/code&gt;, &lt;code&gt;base&lt;/code&gt;. Pick &lt;code&gt;base&lt;/code&gt; if you want to customize from scratch.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;code&gt;themeVariables&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Six variables actually matter: &lt;code&gt;primaryColor&lt;/code&gt;, &lt;code&gt;primaryTextColor&lt;/code&gt;, &lt;code&gt;primaryBorderColor&lt;/code&gt;, &lt;code&gt;lineColor&lt;/code&gt;, &lt;code&gt;fontFamily&lt;/code&gt;, &lt;code&gt;fontSize&lt;/code&gt;. Set those well, ignore the other 50.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Edge curves
&lt;/h3&gt;

&lt;p&gt;Change edge curves from the default to &lt;code&gt;linear&lt;/code&gt; or &lt;code&gt;step&lt;/code&gt;. The default &lt;code&gt;basis&lt;/code&gt; everywhere is one of the top reasons README diagrams look amateur.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Layout direction
&lt;/h3&gt;

&lt;p&gt;Pick based on reading flow. &lt;code&gt;LR&lt;/code&gt; for pipelines, &lt;code&gt;TD&lt;/code&gt; for hierarchies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three rendering pitfalls
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fonts don't render in the saved SVG
&lt;/h3&gt;

&lt;p&gt;Use a system font stack: &lt;code&gt;-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  viewBox cropping
&lt;/h3&gt;

&lt;p&gt;Post-process to add padding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;padViewBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;svgString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;svgString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sr"&gt;/viewBox="&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;?\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\.?\d&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt; &lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;?\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\.?\d&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt; &lt;/span&gt;&lt;span class="se"&gt;(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\.?\d&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt; &lt;/span&gt;&lt;span class="se"&gt;(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\.?\d&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;"/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ny&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`viewBox="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ny&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nw&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nh&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dark mode is hardcoded
&lt;/h3&gt;

&lt;p&gt;Replace fixed colors with &lt;code&gt;currentColor&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeAdaptive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;svgString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;svgString&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/stroke="#&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;0-9a-fA-F&lt;/span&gt;&lt;span class="se"&gt;]{6}&lt;/span&gt;&lt;span class="sr"&gt;"/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stroke="currentColor"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/fill="#&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;0-9a-fA-F&lt;/span&gt;&lt;span class="se"&gt;]{6}&lt;/span&gt;&lt;span class="sr"&gt;"/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fill="currentColor"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When DIY stops being worth the time
&lt;/h2&gt;

&lt;p&gt;Everything above works. I've shipped this exact pipeline.&lt;/p&gt;

&lt;p&gt;It also takes about a day of fiddling to get right, and the result is one diagram style that you maintain forever. The moment you want a different style for a different context — a slide deck vs. a README vs. a postmortem — or someone non-technical on the team wants to make a diagram, the cost-benefit shifts.&lt;/p&gt;

&lt;p&gt;Three signals it's time to stop hand-rolling:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You're maintaining a "diagram theme" file across multiple repos.&lt;/li&gt;
&lt;li&gt;You want a different look for slides vs. docs vs. PRs, but the diagram source stays the same.&lt;/li&gt;
&lt;li&gt;Your inputs aren't just Mermaid — PlantUML, draw.io, AI prompts.&lt;/li&gt;
&lt;/ol&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The shortcut: Paste, pick a theme, export&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.beauty-diagram.com" rel="noopener noreferrer"&gt;Beauty Diagram&lt;/a&gt; is a web editor for Mermaid, PlantUML, and draw.io. Paste your source, pick from 9 production themes, export SVG or PNG. No config files. &lt;em&gt;(Disclosure: I work on it.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;→ Open the editor&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;The fastest path is the &lt;a href="https://www.beauty-diagram.com/editor" rel="noopener noreferrer"&gt;web editor&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Paste&lt;/strong&gt; your Mermaid source on the left.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick a theme&lt;/strong&gt; from nine: &lt;code&gt;classic&lt;/code&gt;, &lt;code&gt;modern&lt;/code&gt;, &lt;code&gt;atlas&lt;/code&gt;, &lt;code&gt;blueprint&lt;/code&gt;, &lt;code&gt;memphis&lt;/code&gt;, &lt;code&gt;obsidian&lt;/code&gt;, &lt;code&gt;slate&lt;/code&gt;, &lt;code&gt;brutalist&lt;/code&gt;, &lt;code&gt;atelier&lt;/code&gt;. Each is a complete design language — typography, palette, edge style, node treatment — tuned so the diagram reads as a finished asset, not a default render.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export&lt;/strong&gt; SVG (vector for docs / repos) or PNG (&lt;code&gt;standard&lt;/code&gt; / &lt;code&gt;high&lt;/code&gt; / &lt;code&gt;max&lt;/code&gt; quality for slides and social).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share&lt;/strong&gt; to get a public hot-linkable URL with an OG preview — drop it into Notion or Linear and it stays live as you edit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zbvucn337gny32s27di.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zbvucn337gny32s27di.png" alt=" " width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's the whole loop. No &lt;code&gt;themeVariables&lt;/code&gt; JSON to maintain. No post-processing scripts. The same renderer powers a CLI if you'd rather automate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Render once, ship to your repo&lt;/span&gt;
npx @beauty-diagram/cli beautify flow.mmd &lt;span class="nt"&gt;--theme&lt;/span&gt; modern &lt;span class="nt"&gt;--out&lt;/span&gt; flow.svg

&lt;span class="c"&gt;# Export at higher quality for slides&lt;/span&gt;
npx @beauty-diagram/cli &lt;span class="nb"&gt;export &lt;/span&gt;flow.mmd &lt;span class="nt"&gt;--theme&lt;/span&gt; atlas &lt;span class="nt"&gt;--format&lt;/span&gt; png &lt;span class="nt"&gt;--quality&lt;/span&gt; max &lt;span class="nt"&gt;--out&lt;/span&gt; flow.png

&lt;span class="c"&gt;# Get a public share URL (with OG preview baked in)&lt;/span&gt;
npx @beauty-diagram/cli share flow.mmd &lt;span class="nt"&gt;--theme&lt;/span&gt; modern &lt;span class="nt"&gt;--title&lt;/span&gt; &lt;span class="s2"&gt;"Auth flow"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI exposes the same nine themes (&lt;code&gt;bd themes&lt;/code&gt; lists them). It does not expose per-variable overrides — the philosophy is that the theme is the choice; you don't tune a theme, you pick a different one. For most readers this is a feature, not a limitation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;Mermaid's defaults aren't bad — they're designed for "the diagram exists" rather than "the diagram is finished". The fixes break down into roughly three tiers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cheap and fine for one style&lt;/strong&gt;: switch &lt;code&gt;theme: 'base'&lt;/code&gt;, set six theme variables, change edge curves, run a viewBox-padding regex.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Annoying past one repo&lt;/strong&gt;: maintain that config across many surfaces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a tool&lt;/strong&gt;: paste, pick, export.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Where you land depends on how much you care about diagrams and how often you ship them.&lt;/p&gt;

&lt;p&gt;If this was useful, drop a ❤️ and follow — I'm posting weekly on diagrams, docs, and developer ergonomics. Next week: &lt;strong&gt;why your GitHub README diagrams look amateur, and the four fixes that take 10 minutes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What's the worst Mermaid diagram you've shipped? Drop a screenshot in the comments — I'll write up the most common issues in a follow-up.&lt;/p&gt;

</description>
      <category>mermaid</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
