---
title: "MermaidKit: We Got Tired of Shipping a Browser to Draw a Flowchart"
description: "A native Mermaid renderer in pure Swift: no JavaScript, no WebView, zero dependencies. All 30 diagram types on six platforms, byte-identical output, usually under 15 milliseconds."
canonical_url: "https://2389.ai/research/writing/mermaidkit/"
last_updated: "2026-09-03T10:20:55-05:00"
doc_version: "1.0"
author: "Clint Ecker"
date: 2026-09-01
tags: ["swift", "mermaid", "diagrams", "open-source", "cross-platform"]
---

# MermaidKit: We Got Tired of Shipping a Browser to Draw a Flowchart

> A native Mermaid renderer in pure Swift: no JavaScript, no WebView, zero dependencies. All 30 diagram types on six platforms, byte-identical output, usually under 15 milliseconds.


[Mermaid](https://mermaid.js.org) lets you write a diagram as plain text, like a flowchart or a sequence chart, and have it drawn for you. Showing one of those diagrams in a native app usually means embedding mermaid.js inside a [`WKWebView`](https://developer.apple.com/documentation/webkit/wkwebview), Apple's built-in browser view. Every diagram then costs you a whole JavaScript engine, a wait while it draws, text that doesn't match the rest of your app, and a web process sitting in your memory the whole time.

It's a lot of machinery to draw a box with an arrow pointing at another box.

So we built MermaidKit: a native Mermaid renderer written in pure [Swift](https://www.swift.org). And no, this doesn't mean it _only_ works on MacOS or iOS. We've got it running on basically every modern platform (and a few not-so-modern ones too).

No JavaScript, no WebView, zero dependencies. You hand it Mermaid source and it hands back a drawn diagram synchronously. Parsing and drawing together usually finish in under 15 milliseconds on Apple silicon. The densest diagrams take about 25. It caches its results, so the second time is free. In SwiftUI, it's a single view:

```swift
MermaidView("""
flowchart TD
    A[Start] --> B{Choice}
    B -->|yes| C[Do it]
    B -->|no| D[Skip]
""")
```

It follows your light or dark mode, sizes itself to the diagram, and if it hits syntax it can't parse, it falls back to readable monospaced text instead of showing a blank rectangle.

## All 30 types, on six renderer targets

MermaidKit parses and lays out all 30 Mermaid diagram types: flowcharts, sequence diagrams, Gantt charts, ER diagrams, state machines, Sankey flow diagrams, and more. Every one of them is in our [gallery](https://2389-research.github.io/MermaidKit/#gallery), rendered by MermaidKit itself, in both light and dark.

### The trick is to separate layout from drawing

The interesting part showed up when we tried to make the same renderer work somewhere other than Apple platforms. The useful trick turned out to be separating "where does everything go?" from "how does this platform draw it?" Swift does the first part once. The result is a small JSON scene description we call **SceneWire**. Then CoreGraphics, Cairo, [Skia](https://skia.org), or standard web graphics does the painting.[^1]

```mermaid
flowchart LR
    A["Mermaid / DOT / SQL / git log"] --> B["Swift parser + layout"]
    B --> C["SceneWire (JSON)"]
    C --> D["Native renderer"]
```

An Android app doesn't need a Swift toolchain in the app. The Swift core ships as a native library, so Android code just passes in Mermaid text and gets back a finished diagram themed to Material Design:

```kotlin
MermaidDiagram("flowchart LR\n A[Start] --> B[End]", Modifier.fillMaxWidth())
```

That Swift core is deterministic: the same diagram always produces the same result. So our automated tests can prove the output is identical down to the byte across the five platforms where the Swift core compiles (Android, Windows, WebAssembly, Linux, and macOS). The sixth renderer target is Flutter, which uses the same SceneWire output through Dart. Same source, same bytes, whether it drew on a Mac or inside a Windows .NET app. There's even a raw-pixels path for screens with no windowing system at all. We have a [demo](https://github.com/2389-research/MermaidKit/tree/main/tools/pi-canvas) that paints an endless, pannable diagram canvas straight onto a Raspberry Pi's framebuffer (the raw screen memory, with no window manager in sight). This was not remotely necessary, but once we realized we could do it, we had to.

## Beyond Mermaid

At some point we realized Mermaid wasn't actually special anymore. The renderer only sees SceneWire, so anything we can turn into that same representation gets the rest of the system for free. That led directly to four more inputs:

- **[Graphviz](https://graphviz.org) DOT** goes in, and MermaidKit can hand it back out, so it doubles as a two-way converter between Mermaid and DOT, two common text formats for graphs.
- **[Dippin](https://dippin.org)** (our own small language for describing AI pipelines, written in `.dip` files) draws its eight kinds of node as flowchart shapes.
- **SQL DDL:** feed in the `CREATE TABLE` statements that define a database and you get an ER diagram back, with primary, foreign, and unique key badges and crow's-foot lines showing how the tables relate.
- **Raw `git log` output** becomes a git graph, with branch lanes drawn from the labels Git attaches to each commit. It renders straight in your terminal.

## Limitations

MermaidKit is not a drop-in reimplementation of mermaid.js. If you need every styling directive or pixel-for-pixel compatibility, use mermaid.js. MermaidKit handles the core syntax of each type (the constructs in the mermaid.js docs' main examples), plus a long list of everyday extras. The README has a [support table](https://github.com/2389-research/MermaidKit#supported-diagram-types--honestly) that spells out exactly what's covered. Styling directives like `classDef` don't cause errors; the parser just skips them, because MermaidKit handles theming itself. And if you need support for older iOS versions, we'll point you to [alternatives](https://github.com/lukilabs/beautiful-mermaid-swift).

Cross-platform rendering also gave us a testing problem: "looks right to me" isn't a useful assertion. So every change runs through a geometric linter (an automated checker that looks at the finished shapes). It verifies that lines don't cut through boxes, that labels don't get clipped, and that the layout stays stable from one run to the next. When a diagram renders wrong, that's a bug you can [report with a template](https://github.com/2389-research/MermaidKit/issues), and we fix it.

MermaidKit is open source under the permissive [MIT license](https://github.com/2389-research/MermaidKit/blob/main/LICENSE), and it's [on GitHub](https://github.com/2389-research/MermaidKit). If you've been shipping a whole browser just to draw boxes and arrows, you can stop now.

[^1]: For the curious: Apple platforms draw with CoreGraphics and CoreText; Linux uses Silica, a Swift binding for the [Cairo](https://www.cairographics.org) graphics library; Android paints with Kotlin's `Canvas`; Windows and .NET use [SkiaSharp](https://github.com/mono/SkiaSharp); Flutter uses a Dart `CustomPainter`; and WebAssembly renders to SVG or Canvas2D. The data moves between languages over the C ABI (the shared calling convention that lets a Kotlin, C#, or Dart program hand a string to Swift and get pixels back), using each language's standard bridge for that job: JNI on Android, P/Invoke on Windows, and `dart:ffi` on Flutter.


## Sitemap

Parent: [Writing](https://2389.ai/research/writing/index.md)

Related pages in this section:

- [Two Months of Dippin: Edges Own Everything Now](https://2389.ai/research/writing/dippin-edges-own-everything/index.md)
- [Postique: AI Marketing Employee](https://2389.ai/research/writing/postique/index.md)
- [The team you lose when you open Claude Code](https://2389.ai/research/writing/review-squad/index.md)
- [Horton Hears a Whisper](https://2389.ai/research/writing/horton-hears-a-whisper/index.md)
- [Why We Built a Language for AI Pipelines](https://2389.ai/research/writing/why-we-built-a-language-for-ai-pipelines/index.md)
- [Word Compiler, A Context Compiler for Long-Form Fiction](https://2389.ai/research/writing/word-compiler/index.md)
- [We Turned a 3D Printer Into an AI Portrait Artist](https://2389.ai/research/writing/we-turned-a-3d-printer-into-an-ai-portrait-artist/index.md)
- [Simmer: A Self Honing Skill](https://2389.ai/research/writing/simmer-skill/index.md)
- [Cookoff: Same Spec, Different Code](https://2389.ai/research/writing/cookoff-same-spec-different-code/index.md)
- [Omakase: Show Me](https://2389.ai/research/writing/omakase-show-me/index.md)


Site index: [llms.txt](https://2389.ai/llms.txt) · [sitemap.md](https://2389.ai/sitemap.md) · [HTML](https://2389.ai/research/writing/mermaidkit/)
