what are text-to-diagram tools?
If you have a system architecture to describe, are comfortable writing code, and find page layout tools like PowerPoint tedious, then text-to-diagram tools could be perfect for you. Text-to-diagram tools use automatic layout algorithms, leaving you free to focus on the content of your diagram while the tool figures out how to arrange it. Gone are the days of dragging a dozen shapes around because you forgot a step in your process.
A diagram’s “code” can be composed in a text editor and tracked in a version control system like Git, making the workflow particularly comfortable for developers. There are two popular open-source tools in this space: Mermaid and D2. This post compares the two, with a focus on developer experience, unique capabilities, and rendering workflows.
mermaid vs d2: feature comparison
I’m primarily interested in flowcharts and software architecture diagrams, which both packages support well, so this comparison won’t focus on chart types so much as developer experience and unique capabilities.
Feature | Mermaid | D2 | Winner |
---|---|---|---|
Theming | small set of built-in themes with customziation via JS-like syntax inside %% blocks. | wider variety of publication-quality themes that apply to both diagrams and code blocks. customizing themes is marginally less awkward. | D2 |
Responsive light/dark mode | light/dark mode is set via configuration in JS code. static diagrams might require separate light/dark versions. | light/dark mode responds to both user preference and common theme switcher conventions using CSS media queries. | D2 |
Code blocks | Not supported | syntax-highlighted code blocks can be embedded as nodes in a diagram, with configurable themes and light/dark mode. | D2 |
Animations | manual, through click callbacks on nodes; requires interaction or external JavaScript. | built-in, define scenarios and an animation interval. CSS animations to animate lines are also supported. | D2 |
Interactivity | defining click callbacks and/or links on nodes is possible | no callbacks, but SVGs can contain links and tooltips unless embedded as an img | Mermaid? interactive diagrams are better handled by a separate tool |
Fonts | not embedded in SVGs; if rendered in a browser, positions can adjust based on font size/availability. static diagrams may require font download or preloading for consistent rendering. | fonts are base64-embedded in the generated SVG for maximum consistency since diagrams can’t adjust for font differences. this bloats the SVGs unless fonts are shipped separately. | Mermaid? Nobody really wins when web fonts are involved. |
SVG icons | mermaid doesn’t support custom SVG images for nodes | can link SVG icons via URL or local file path; icons are embedded in the generated SVGs. | D2 |
Server-side rendering | ⚠️ Requires headless browser | ✅ Native CLI tool | D2 |
Client-side bundle size | ⚠️ 158kb gzipped | client-side rendering is theoretically possible but not supported outside the official playground | Mermaid wins by default; D2’s webassembly backend is not publicly available. |
Learning curve | ⚠️ Multiple syntaxes: each chart type has its own syntax | ✅ Single consistent syntax | D2 |
Sketch mode | Not supported | built-in excalidraw-inspired hand-drawn mode | D2 |
Astro integration | best pursued through rehype-mermaid, which hooks into MDX processing. astro-diagram has gone 2 years without an update. | astro-d2 provides an Astro & MDX API for the D2 CLI tool, generating diagrams from MDX code blocks at build/development time. | D2 |
d2: the upstart
D2 emerged in Mermaid’s shadow and its developers have clearly learned from Mermaid’s successes and failures.
Unlike Mermaid, which is written in JavaScript and renders in a browser, D2 is written in Go and renders diagrams using a browser-free command line utility1. D2’s other major selling point is its unified syntax, which is more verbose but significantly less arcane than Mermaid’s.
D2 has a bunch of additional nice-to-have features, outlined in the table above, that make it easier to create professional-looking diagrams. D2 is the engine behind TerraStruct’s commercial suite of visual documentation tools, which is an encouraging sign regarding ongoing improvement and support.
d2 integrates well with Astro
Befitting a tool designed to document software systems, using D2 to render diagrams as part of a static Astro build feels natural, especially thanks to HiDeoo’s astro-d2 integration2. Composing a diagram is as simple as adding a d2
code block.
Astro-d2 then passes your d2 code to the command line renderer, saves an SVG to the public
directory, and displays the diagram on your page as an image. Astro-d2 can be configured to save the diagram elsewhere and/or inline the SVG in your MDX output. While developing locally, your diagrams update in the browser within a second of saving changes, facilitating a quick feedback loop.
mermaid: the heavyweight
Mermaid.js is much older and better established than D2. It’s popular enough that GitHub will render Mermaid diagrams in ReadMe.md files directly in the browser, which helps drive Mermaid’s popularity. Mermaid’s achilles heel is that it relies on a browser engine to render diagrams, which means that you either need to ship the Mermaid.js library and render client-side or use a headless browser for server-side rendering.
client-side mermaid
Rendering Mermaid diagrams entirely client-side is the classic way to use Mermaid. Mermaid’s “Getting Started” docs demonstrate importing mermaid
from a CDN and calling the mermaid.initialize()
function to render diagrams when your page loads in your visitor’s browser. This approach is straightforward, but not particularly performant. Mermaid.js has been on a diet lately, but it’s still a heavy dependency, weighing in at 158kb minified and gzipped3. If you’re using a lightweight framework like Astro or SvelteKit to build your site, then Mermaid could easily double the total amount of JavaScript that your visitors need to download, which feels deeply anti-climactic.
Mermaid.js also provides an NPM package that you can use to build your own component to render diagrams. Bundling Mermaid as part of your own site’s build might allow for some size reduction via “tree shaking,” which is when unused functions and modules are excluded from the code your visitors have to download. No matter how you integrate Mermaid, however, diagrams are only going to be rendered inside a browser, even if you’re using a framework that supports server-side rendering.
server-side mermaid
Mermaid does have an official CLI tool, but it’s a actually just a wrapper that uses headless Chrome, via Puppeteer, to run the browser-based package on the server or build machine. This reliance on headless Chrome at build time adds a lot of overhead. Moreover, it also means that you need to use a more fully-featured builder image than you might otherwise opt for. Despite the apparent hackiness, this is a well-established way to add Mermaid diagrams to a static site. There are several third-party tools that render Mermaid.js diagrams as an Astro integration or a rehype plugin, which allow for automatic mermaid diagram generation in your blog’s static build process.
mermaid: server-side workflow with MDX
conclusion
D2 is a better all-around tool than Mermaid. Technical details aside, it produces nicer-looking diagrams than Mermaid, with better out-of-the-box theming and seamless integration with websites that use separate light/dark themes. The ability to embed SVG icons adds a lot of value in a visual medium like diagrams. Every feature that D2 adds over Mermaid, like CSS animations and embedded syntax-highlighted code blocks, makes your diagrams come across as more polished and professional.
Unless you already have a large body of Mermaid diagrams that you want to publish, or you need a particular Mermaid diagram type that hasn’t made its way to D2 yet, D2 is the better choice. The fact that D2 itself installs outside of a package manager like NPM does add some complexity, but it’s not any worse than having to install a headless browser to server-side render Mermaid diagrams. Mermaid does win in terms of support for client-side interactivity and re-rendering, but if you really want to include an interactive diagram in your user interface you’re going to be better served by a tool like React Flow.
I’m just getting started with D2. Expect more examples of its capabilities in future blog posts.
Footnotes
D2 can run in a browser using WebAssembly, but WebAssembly deployment only makes sense if you want to allow users to edit or build their own diagrams through a browser-based frontend. TerraStruct, the company behind D2, uses a WASM version of D2 to power their interactive D2 Playground but releasing this WebAssembly backend to the public doesn’t seem to be a priority. ↩
Astro-d2 includes an MDX plugin that could probably be adapted for use with MDX documents in other frameworks. I haven’t tried, though, and wasn’t able to find a framework-agnostic D2 MDX plugin. ↩
Mermaid.js uncompressed is 565kb at the time of this writing. Bundle size has come down significantly since early 2023, when Mermaid.js weighed over 2mb uncompressed. ↩