Tool Comparisons

Mermaid Diagrams in Markdown — Flowcharts From Plain Text

How Mermaid turns fenced code blocks into diagrams: syntax basics, where it renders (GitHub, Obsidian, Notion), what it does badly, and how AI writes it.

Kostja18 min read
Mermaid Diagrams in Markdown — Flowcharts From Plain Text

1. The Idea: Diagrams as Code

Every diagram tool before Mermaid stored drawings. The file described shapes and coordinates, and editing meant dragging boxes until the arrows looked right. The file was opaque to version control, impossible to diff, and painful to update.

Mermaid inverts this. A diagram is declared as text inside a regular Markdown fenced code block:

```mermaid
flowchart LR
    A[Draft in Markdown] --> B{Human reads it?}
    B -- yes --> C[Render as HTML]
    B -- machine reads it --> D[Keep as Markdown]
```

Direction is a single token — LR for left-to-right, TD for top-to-bottom — and it is the first layout decision every diagram makes. The same graph, read top down:

```mermaid
flowchart TD
    A[Draft in Markdown] --> B{Human reads it?}
    B -- yes --> C[Render as HTML]
    B -- machine reads it --> D[Keep as Markdown]
```

A renderer replaces the block with a drawn flowchart. The source stays plain text: reviewable in a pull request, editable in any editor, and understandable even where Mermaid does not render — the text reads like pseudocode for the diagram.

2. What Renders It — and What Doesn't

As of 2026, GitHub renders Mermaid blocks natively in files, issues, and pull requests. Obsidian renders them in notes, which turned it into a default tool for thinking-in-diagrams. Most documentation generators render them too — Docusaurus and MkDocs have Mermaid support built in or one plugin away, which is why Markdown documentation sites and Mermaid tend to be adopted together.

Not everything renders it. Strict CommonMark has no idea what a mermaid code block means; some older or minimal renderers show the source as a plain code block, which is the graceful failure mode — readable pseudocode rather than a broken image. The practical check is the same one tables need: render once in the platform you actually publish to before relying on it. A browser-based Markdown preview is a quick spot-check for whether your renderer's GFM coverage includes what you wrote, though Mermaid specifically depends on the platform's own integration.

3. A Rendering Matrix for Real Platforms

Where does Mermaid actually work? The honest answer is a matrix rather than a yes or no, because every platform bundles its own copy of the Mermaid library and upgrades it on its own schedule. The same block can render perfectly in one tool and show raw text in another, and a diagram type that works everywhere today can fail on a platform pinned to an older release. The matrix below reflects practical day-to-day behavior as of 2026 rather than vendor promises — and the fastest way to extend it to your own stack is to paste one small diagram into each tool you publish to and look at what comes back.

PlatformNative renderingVersion behaviorFailure mode
GitHubFiles, issues, pull requestsPins a Mermaid release; new diagram types arrive latePlain code block
ObsidianNotes and live previewBundled version updates with the appPlain code block
NotionNo native Mermaid blockN/A — shows source; embed the live editor for a pictureSource code
VS Code previewNot built inAn extension adds it; the extension sets the versionPlain code block
Docusaurus / MkDocsPlugin or built-in theme supportYou control the pinned version in configBuild warning or code block

The version column is the one people underestimate. Mindmaps, for example, arrived in the Mermaid 9.3 release, and a platform pinned to an older version will not draw them no matter how correct the syntax is. A documentation site you control can bump the library in config and get new diagram types immediately; GitHub upgrades globally, on GitHub's schedule and nobody else's. The workable rule: treat the newest diagram types as optional sugar, and keep diagrams that must render everywhere on the conservative core — flowchart, sequence, ER, state, gantt, pie.

The failure column is the reason this trade is acceptable. On almost every platform, unsupported Mermaid degrades to a plain code block — the readable-pseudocode failure mode rather than a broken image — so a diagram that fails never destroys the information around it. Notion is the outlier worth planning around: it shows the source and nothing else, and the common workarounds, embedding the Mermaid live editor or pasting an exported image, give up the very property that makes text diagrams valuable, which is that the source lives and versions with the document. The render-once check is the same discipline Markdown tables demand, only applied per platform instead of per document.

4. The Diagram Types Worth Knowing

Mermaid covers far more than flowcharts, and four types cover most real use.

Flowcharts (flowchart LR or TD) are the workhorse: boxes, decisions, and arrows for processes and decision trees. Sequence diagrams map exchanges between participants — the honest picture of an API conversation or an agent handoff. Entity-relationship diagrams describe database schemas. Gantt charts describe schedules. State diagrams earn a place on that list too, and two quick-sketch types — pie and mindmap — round out the tour below.

The syntax stays close to English: A --> B connects two nodes, labels ride on the arrows (B -- yes --> C), and shapes change meaning ([brackets] for process boxes, {braces} for decisions). Mermaid's official documentation is the reference, and it is genuinely readable — the language was designed for non-designers.

4.1 Sequence Diagrams: Who Talks to Whom, in What Order

```mermaid
sequenceDiagram
    participant B as Browser
    participant A as API
    participant D as Database
    B->>A: POST /login (credentials)
    A->>D: SELECT user WHERE email = ?
    D-->>A: row or empty
    A-->>B: 200 token, or 401
```

Two annotations earn their keep once diagrams land in code review. autonumber stamps every message with a step number, so an issue can say "step 3 fails" and everyone sees the same edge; Note over spells out shared context that would otherwise live in a side channel:

```mermaid
sequenceDiagram
    autonumber
    participant B as Browser
    participant A as API
    B->>A: POST /login (credentials)
    A-->>B: 401 invalid password
    Note over B,A: lock account after 5 tries
```

Participants become columns and messages become rows, so the picture matches the way an API conversation actually reads in a log. Solid arrows carry requests, dashed arrows carry responses back, and the top-to-bottom reading order is the order things happen in. This is the type developers reach for first after flowcharts, because author and reviewer read it the same way. When a sequence diagram needs more than about five participants, the conversation itself is usually the thing that needs redrawing.

4.2 State Diagrams: One Thing's Life Story

```mermaid
stateDiagram-v2
    [*] --> Queued
    Queued --> Running: worker picks it up
    Running --> Waiting: tool needs approval
    Waiting --> Running: approved
    Running --> Done: exits cleanly
    Done --> [*]
```

Real lifecycles also fail, and the transition lines carry that as easily as the happy path. The same task with a retry loop and a terminal failure state:

```mermaid
stateDiagram-v2
    [*] --> Queued
    Queued --> Running
    Running --> Failed: tool error
    Failed --> Running: retry
    Failed --> Abandoned: retries exhausted
    Abandoned --> [*]
```

States are nouns and transitions are the events that move an object between them, which makes the syntax close to a literal transcription of a state machine definition. The typical subjects are things with a lifecycle: a task, an order, a deployment, a document under review. The distinction from a flowchart is worth keeping sharp — a flowchart answers "what happens next in this process," while a state diagram answers "what is this one thing allowed to do next."

4.3 Entity-Relationship Diagrams: Schemas as Text

```mermaid
erDiagram
    AUTHOR ||--o{ POST : writes
    POST ||--|{ COMMENT : receives
    TAG }o--o{ POST : labels
```

The same diagram carries attribute blocks when column names start mattering in the conversation. Under each entity, plain type-and-name lines list the fields:

```mermaid
erDiagram
    AUTHOR ||--o{ POST : writes
    POST ||--|{ COMMENT : receives
    AUTHOR {
        string name
        string email
    }
```

Crow's-foot notation compresses into a few punctuation marks: ||--o{ reads as one-to-zero-or-many. In a design discussion, the relationship lines alone are usually enough, and the attribute block under each entity can wait until the schema is serious. The payoff is the same as everywhere else in Mermaid: the schema sketch lives in the pull request that proposes it, and edits to it show up as a readable diff.

4.4 Gantt Charts: Schedules That Survive Edits

```mermaid
gantt
    title Launch week
    dateFormat YYYY-MM-DD
    section Content
    Draft posts      :a1, 2026-10-01, 3d
    Review and edits :after a1, 2d
    section Site
    Build and deploy :2026-10-07, 1d
```

Durations chained with the after keyword, rather than absolute dates, express the same week as pure dependencies — change one duration and everything downstream moves:

```mermaid
gantt
    title Dependencies, not dates
    dateFormat YYYY-MM-DD
    section Chain
    Write  :a1, 2026-10-01, 2d
    Edit   :a2, after a1, 2d
    Deploy :a3, after a2, 1d
```

Sections group related tasks, and each task is a name plus a duration, so a schedule edit is a one-line change. Among the main types this is the least text-native — nobody enjoys doing date arithmetic by hand — and multi-month programs with resource leveling belong in a real planning tool. A launch week or a content sprint, though, holds up well, and it stays reviewable in a way no spreadsheet screenshot is.

4.5 Pie and Mindmap: The Quick-Sketch Types

```mermaid
pie title Time per article
    "Research" : 35
    "Drafting" : 40
    "Editing" : 25
```
```mermaid
mindmap
  root((Markdown))
    Writing
      Cheat sheet
      Tables
    Diagrams
      Flowcharts
      Sequence
```

A pie chart earns its keep in postmortems and time audits, where three to five slices tell the story and more than that turns into noise. A mindmap is the first five minutes of brainstorming: there are no arrows to think about, only indentation, which is why it pairs so naturally with outliners like Obsidian. Both render small and read instantly, which is exactly the bar a text-based diagram should clear.

5. Syntax Traps Worth Knowing Before You Paste

Mermaid reads like English right up until a diagram fails to parse for a reason that takes ten minutes to find. The good news is that nearly every syntax failure traces back to a handful of habits, and they are the same across diagram types. If you already keep a Markdown cheat sheet open for the rest of Markdown's punctuation rules, Mermaid adds exactly one new habit — quote the label — plus the three smaller points below.

5.1 Quote Any Label That Isn't a Plain Word

Any label containing punctuation — parentheses, colons, commas, question marks — must be wrapped in double quotes, or the parser tries to read that punctuation as syntax. The failure is confusing because the diagram parses fine right up to the first special character and then dies mid-line, which makes the broken version and the fixed version worth seeing side by side:

```mermaid
flowchart TD
    login[Login: attempt 2 (retry)] --> check{quota > 0?}
```
```mermaid
flowchart TD
    login["Login: attempt 2 (retry)"] --> check{"quota > 0?"}
    check -- yes --> dash["Dashboard"]
    check -- no --> pay["Upgrade page"]
```

The broken block dies on the unquoted colon, the parentheses, and the comparison inside the braces; the fixed one quotes every label and parses anywhere. Two label positions still bite after you adopt the quoting habit. An arrow label containing a pipe is the classic, because pipes delimit the arrow-label syntax — quoting the text inside the pipes defuses it — and a square-bracket label that itself contains square brackets has a nesting problem quotes alone do not solve; rename the inner text instead.

5.2 Node IDs and Node Labels Are Different Things

In A[Review queue], the A is the node ID and the bracketed text is only what gets displayed. Every edge, style rule, and class assignment references the ID, which means display text can be rewritten without touching the graph's wiring. IDs must be unique, cannot contain spaces, and earn their keep when they name a concept — review, publish — rather than a letter. One reserved-word trap is worth memorizing: a node IDed as lowercase end collides with the keyword that closes subgraphs, so call it finish or quote it.

5.3 Comments and Statement Separators

A %% prefix comments out the rest of a line, which is the sanctioned way to leave notes inside a diagram. Statements separate on newlines; semicolons work as separators too, so A --> B; B --> C on one line is legal. The trap runs in the other direction: a semicolon inside an unquoted label terminates the statement early, which is rule one — quote the label — wearing a different hat.

5.4 Chinese and Other Non-ASCII Labels

Chinese, Japanese, and Korean labels render correctly on the major platforms, and a bilingual diagram — ASCII keywords, Chinese display text — is entirely normal in practice. The diagram-type and direction keywords (flowchart, LR, sequenceDiagram) stay ASCII; only the labels carry local text. Two caveats keep surprises away: quote CJK labels containing full-width punctuation, and remember that some SVG and PDF export paths substitute fonts, which changes text width and can nudge a tight layout. Check the exported file, not just the live preview.

6. What Mermaid Does Badly

Honesty about the limits keeps diagrams maintainable. Precise layout control is not a Mermaid feature: the auto-layouter decides where boxes sit, and large graphs — more than a dozen nodes with cross-links — become unreadable hairballs no matter how carefully you write them. Pixel-perfect corporate styling is not the goal either; themes exist, but fine-grained brand styling fights the tool. And interactive or animated diagrams are out of scope entirely.

The pragmatic rule: Mermaid excels at small, structural diagrams that document logic — flows, sequences, schemas. It fails gracefully at poster-grade visuals. When a diagram needs to be beautiful, that is a job for a drawing tool; when it needs to be true, current, and versioned, that is Mermaid.

7. Themes and Styling: Less Than You're Offered

Mermaid ships themes — default, neutral, dark, forest, and base — and an init directive can select a theme and override its variables from the first line of any block. It is tempting to reach for that the first time a diagram goes into a branded document. The workmanlike advice is to use less styling than the tool offers, because styling is the part that stops being true when the diagram leaves the platform you tuned it on. What the directive looks like in full:

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#eef4ee'}}}%%
flowchart LR
    A[Draft] --> B[Review] --> C[Publish]
```

The version that actually ships, though, usually skips the directive entirely — default theme, one accent reserved for meaning:

```mermaid
flowchart LR
    A[Draft] --> B[Review] --> C[Publish]
    classDef shipped fill:#2e7d32,color:#ffffff
    class C shipped
```

The init line must be the first line of the block, and everything it sets applies to that diagram alone. classDef covers the middle ground: define a named style once, then apply it to the nodes whose color means something — shipped, failed, waiting on a human. That is the entire legitimate use of color in a Mermaid diagram: encoding state, not decorating boxes.

There is also a dark-mode test hiding in this section. GitHub and Obsidian both flip themes, and a diagram tuned to look right on white — pale fills, light gray text — can wash out completely on dark. If a diagram needs custom colors to be readable, run it through both themes before it ships; if it uses the default theme with one accent, it usually survives both untouched.

8. AI Writes Mermaid Well

Describing a diagram in plain language and receiving editable diagram code is a near-perfect LLM task, and it has quietly changed how diagrams get made. Paste a process description to an agent, ask for a Mermaid flowchart, and the output is text you can fix by editing words — no canvas, no dragging.

This closes a loop with the rest of the Markdown ecosystem. An agent that reads a Markdown document can propose its architecture diagram in the same file format; a reviewer reads the diff of a diagram as text. The diagram becomes just another part of the document that AI pipelines read and edit natively — which is the entire reason text-based diagrams belong in a Markdown workflow at all.

8.1 A Prompt Pattern That Works

The reliable pattern is to state the diagram as facts before asking for code: the diagram type and direction, the participants by name, and the ordered list of messages or steps between them. A prompt that says "sequence diagram, top to bottom, participants Browser, API, Database," followed by the four messages in order, returns text that usually parses on the first try. Two constraints make it sturdier: a node budget — under ten, or the layout will suffer — and the quoting rule from the syntax section, restated so the model applies it.

Draw a Mermaid sequence diagram, top to bottom.
Participants, in order: Browser, API, Database.
Messages, in order:
1. Browser sends POST /login with credentials
2. API queries the Database for the user
3. Database returns the row, or empty
4. API returns 200 with a token, or 401
Keep it under 8 nodes. Quote any label containing punctuation.

The prompt works because it is just the diagram described honestly — participants and sequence are the actual content of a sequence diagram, so the model is transcribing rather than inventing. Direction and participant order decide the layout, which is why they belong in the prompt instead of in after-the-fact edits. And if the first output is structurally right but cosmetically wrong, fix the words; regenerating a whole diagram to move one arrow is the canvas habit sneaking back in.

8.2 What to Check Before You Trust the Output

Trust the structure, verify the details. The checks that matter: every edge label states what actually triggers the transition; participants appear in the order they occur in reality; no node exists that the source process does not justify; and the diagram types used are supported on the platforms in the rendering matrix, not only in the newest Mermaid release. None of this is harder than reviewing a paragraph of prose — which is precisely the point.

The syntax errors AI makes most are the ones from the traps section: unquoted punctuation in labels, a lowercase end used as a node ID, inconsistent arrows (--> where a plain -- was meant), and mindmaps indented with tabs instead of spaces. All of them are one-word fixes, which keeps the edit loop fast. An error that takes longer than a minute to find is usually a platform version gap rather than a syntax mistake, and the rendering matrix above is the first place to look.

9. Splitting a Diagram That Grew Too Big

Every Mermaid user eventually meets the diagram that grew. A release-notes pipeline started as a six-node flowchart; six months later it had twenty nodes and twenty-six edges spanning drafting, review, publishing, and distribution, and the auto-layouter wrapped it into a shape no reviewer could follow. Redrawing it smaller was not an option — all twenty nodes were real — so the fix was to split it along its natural joints.

The joints were the hand-offs where a different person or tool takes over, and they grouped the graph into three clusters: the draft loop, the review gate, and publish-and-distribute. Each cluster became its own diagram with explicit boundary nodes — an entry node like From review, an exit node like To distribution — so a reader can enter any sub-diagram and see where it hands off. A short indexed list in the text above the three diagrams now does the routing that the tangled cross-links used to do, and every sub-diagram stayed under eight nodes, comfortably inside the territory where the layout remains legible.

```mermaid
flowchart LR
    In([From review]) --> gate{"Approved?"}
    gate -- yes --> schedule[Schedule post]
    gate -- changes --> revise[Request changes]
    revise --> In
    schedule --> Out([To distribution])
```

The publish-and-distribute cluster keeps the same convention, and its entry node repeats the gate's exit so the hand-off reads the same in both directions:

```mermaid
flowchart LR
    In([From distribution]) --> render[Render site]
    render --> ping[Ping sitemap]
    ping --> social[Queue social posts]
    social --> Done([Post shipped])
```

The split cost about twenty minutes, and the readable result has survived a dozen edits since. The lesson generalizes: when a Mermaid diagram stops being readable, the answer is almost never styling — it is that the diagram is carrying more than one idea, and each idea deserves its own block. Three small, boring, true diagrams beat one impressive hairball every time the document has to be maintained.

10. Conclusion

Mermaid turns the least maintainable artifact in documentation — the diagram — into a few lines of text that live, diff, and die with the document. The syntax takes minutes, the rendering support is broad as of 2026, and the failure mode everywhere else is readable pseudocode.

Next time a process explanation needs a picture, try describing the picture instead of drawing it.

https://floatboat.ai/blog/mermaid-diagrams-in-markdown

Frequently Asked Questions

Can Mermaid draw the whole UML family?
Partially, and it does not aim for full UML compliance. Mermaid covers class diagrams, sequence diagrams, state diagrams, and flowcharts standing in for component behavior, which handles the everyday majority of what teams use UML for. What it lacks are the formal corners — object diagrams, interaction overviews, profile support — and any process that requires a certified UML tool should keep using one. For documenting logic inside a repository, the Mermaid subset is usually enough.
Can I export a Mermaid diagram to SVG or PNG?
Yes, through three main routes. The Mermaid Live Editor exports SVG and PNG directly in the browser; mermaid-cli (mmdc) renders diagram files from the command line for build pipelines; and some platforms expose their own paths, such as Obsidian export plugins or an embedded live editor in tools that do not render natively. SVG is the better default because it scales, while PNG is the safe harbor for slides and tools that mangle SVG.
Does Mermaid work offline?
Yes, wherever the library ships with the tool. Obsidian bundles Mermaid locally, so diagrams render with no network connection, and documentation sites bundle it into their built assets the same way they bundle any JavaScript. What needs a connection is the browser-based live editor and any platform that renders diagrams outside your machine. If offline rendering is a hard requirement, the check is simply whether the tool vendors the library — most desktop and self-hosted tools do.
How does Mermaid compare to PlantUML?
They solve the same problem — diagrams as text — with different instincts. PlantUML is older, deeper, and covers more formal notations, at the cost of a Java runtime and syntax that reads more like a programming language; Mermaid is JavaScript-native, renders on more Markdown platforms out of the box, and reads closer to English. Teams that live in GitHub or GitLab Markdown usually land on Mermaid for portability, while teams generating diagrams from structured data often prefer PlantUML's expressiveness. Both degrade to readable text where they do not render.
Do version differences between platforms matter in practice?
Less than they used to, more than you would like. The core types — flowchart, sequence, ER, state, gantt, pie — render consistently everywhere that renders Mermaid at all; the friction concentrates in newer types like mindmap and in occasional syntax changes between major versions. The workable rule is to reserve new diagram features for places where you control the renderer and to keep shared diagrams on the conservative core. When a diagram renders on your machine but not on a platform, check the version pin before rewriting the code.