Every diagram here is written as plain text. The left column is Mermaid, parsed in your browser. The right is Graphviz, compiled to SVG before the page was built. Same information, two engines, and the differences are the point.
Both are self-hosted, so this page still makes no third-party requests. Mermaid costs 3.4 MB of JavaScript and is opt-in per page — no other post on this site loads it. Graphviz costs nothing at runtime; it runs on my machine and ships a static SVG.
Everything below follows the theme toggle in the header. Mermaid re-renders on a palette change; the Graphviz SVGs are inlined rather than linked, so the same CSS variables that colour this page colour them.
Flowchart
The two-stage login from the OGame scraper.
Mermaidin the browser
flowchart TD
A[POST credentials] -->|valid| B[200 OK<br/>bearer token]
A -->|invalid| C[403 Forbidden]
B --> D[GET accounts]
Graphvizat build time
The Graphviz source says things Mermaid has no syntax for:
{ rank=same; ok; bad } // the fork reads as a fork
post -> ok [label="valid", weight=10]; // straighten the path that matters
post -> bad [constraint=false]; // dead end stops distorting layout
ok:e -> acct:w; // exact compass attach points
State machine
The SWJ-DP, and the one-way door into a locked part.
Mermaidin the browser
stateDiagram-v2
[*] --> JTAG: power-up
JTAG --> SWD: 0xE79E
SWD --> JTAG: 0xE73C
SWD --> Locked: SWJ_CFG=100
Locked --> SWD: BOOT0 + reset
Graphvizat build time
Class diagram
Mermaidin the browser
classDiagram
class Service {
+String name
+Number port
+start()
}
class UniverseService {
+exists(name, lang)
}
class AccountService {
+listForPlayer(token)
}
Service <|-- UniverseService
Service <|-- AccountService
Graphvizat build time
That <|-- is worth a note. A shortcode that passes its body through
unescaped hands the browser a < followed by a pipe, and the parser has
opinions. Escaping it is what makes the class diagram survive.
Entity relationship
Mermaidin the browser
erDiagram
PLAYER ||--o{ ACCOUNT : owns
ACCOUNT }o--|| UNIVERSE : "lives in"
UNIVERSE {
string name
string language
int playerCount
}
ACCOUNT {
string id
string server
}
Graphvizat build time
Commit history
Mermaidin the browser
gitGraph
commit id: "jekyll"
branch zola
checkout zola
commit id: "port content"
commit id: "workshop design"
commit id: "diagrams"
Graphvizat build time
Where Graphviz simply has nothing
Three of the diagram types below have no Graphviz equivalent. Not a harder equivalent — none. Graphviz draws graphs: nodes joined by edges. A sequence diagram is a timeline, a gantt is a calendar, a pie is a proportion, and none of those are graphs.
Sequence
sequenceDiagram
participant H as Host
participant T as Target
H->>T: 8-bit request
Note over H,T: turnaround
T-->>H: 3-bit ACK
Note over H,T: turnaround
H->>T: 32 data bits + parity
Gantt
gantt
title Posts, by project
dateFormat YYYY-MM-DD
axisFormat %Y
section STM32
Setting it all up :done, 2018-06-02, 90d
How SWD actually works :active, 2026-08-21, 60d
section OGame
Initial design :done, 2020-08-23, 40d
Microservices :done, 2020-09-27, 40d
section Go
Golang notes :done, 2022-10-16, 60d
Pie
pie showData
title Code in these posts, by language
"C" : 96
"ARM asm" : 34
"JavaScript" : 88
"JSON" : 62
"Makefile" : 44
Bars
xychart-beta horizontal
title "Code in these posts, by language"
x-axis [C, "ARM asm", JavaScript, JSON, Makefile]
y-axis "lines" 0 --> 100
bar [96, 34, 88, 62, 44]
What the comparison actually shows
Mermaid wins on breadth and on effort. It has diagram types Graphviz will never have, the source lives in the post, and there is no build step. It also renders on GitHub, so the markdown is not inert in the repository.
Graphviz wins on control and on weight. rank, weight, constraint,
group and compass ports let you insist on an arrangement rather than accept
one, and the reader downloads no JavaScript at all. The cost is a separate
file per diagram and a script that has to run before the site builds.
The honest split: Mermaid for diagrams where the shape does not carry meaning, Graphviz when it does or when the page should stay free of JavaScript. Neither is the default; the diagram decides.