Mermaid Test Post 4
Mermaid stress test 4 — time and work
Gantt, timeline, journey, kanban and gitGraph. Every one of these states how far along something is, so this part is where a borrowed hue shows up as a lie rather than as a wrong colour.
Gantt — every task state
Done, active, critical, milestones, and a task with no state at all.
gantt
title Roadmap
dateFormat YYYY-MM-DD
axisFormat %b %d
section Build
Editor :done, a1, 2026-01-01, 20d
Renderer :active, a2, after a1, 15d
Spike :crit, a3, after a1, 6d
Cleanup : a4, after a2, 8d
Feature complete :milestone, m1, after a4, 0d
section Ship
Polish : b1, after m1, 10d
Launch :crit, active, b2, after b1, 4d
Shipped :milestone, m2, after b2, 0d
Gantt — weekends excluded, and a long span
gantt
title A year of work
dateFormat YYYY-MM-DD
excludes weekends
section Q1
Discovery :done, q1a, 2026-01-05, 30d
Build :done, q1b, after q1a, 45d
section Q2
Migration :active, q2a, 2026-04-01, 60d
section Q3
Hardening :q3a, 2026-07-01, 45d
section Q4
Launch :crit, q4a, 2026-10-01, 30d
Gantt — hours rather than days
gantt
title A deploy window
dateFormat HH:mm
axisFormat %H:%M
section Cutover
Freeze writes :done, c1, 01:00, 15m
Migrate :active, c2, after c1, 45m
Verify :c3, after c2, 30m
Unfreeze :milestone, c4, after c3, 0m
Timeline
timeline
title History of the site
2023 : first deploy
2024 : blog : books
2025 : activity feed : heatmaps
2026 : projects : diagrams : the ramp
Timeline — with sections
timeline
title Two eras
section Static
2022 : a single page
2023 : a blog
section Live
2024 : anime and music
2025 : screen and steam
2026 : projects
User journey
journey
title Publishing a post
section Draft
Write: 5: Me
Reread: 3: Me
Regret the title: 1: Me
section Ship
Publish: 5: Me
Share: 4: Me, Reader
Read it again: 3: Reader
Kanban
kanban
Todo
[Write the post]
[Fix the sync]
[Answer the issue]
Doing
[Ship diagrams]
Blocked
[Wait on upstream]
Done
[Ramp tokens]
[Theme sweep]
Kanban — with metadata
kanban
Backlog
task1[Rebuild the heatmap]@{ ticket: PORT-1, assigned: jerry, priority: High }
Doing
task2[Fold the migrations]@{ ticket: PORT-2, assigned: jerry, priority: Low }
Done
task3[State the ramp]@{ ticket: PORT-3, priority: Very High }
gitGraph — branches, merges, tags
gitGraph
commit id: "init"
branch develop
checkout develop
commit id: "editor"
branch feature/diagrams
checkout feature/diagrams
commit id: "node view"
commit id: "island"
checkout develop
merge feature/diagrams
branch hotfix
checkout hotfix
commit id: "ramp tokens" type: HIGHLIGHT
checkout main
merge hotfix tag: "v1.0.1"
merge develop tag: "v1.1.0"
gitGraph — nine branches, past the ramp's eighth
gitGraph
commit
branch one
commit
branch two
commit
branch three
commit
branch four
commit
branch five
commit
branch six
commit
branch seven
commit
branch eight
commit
branch nine
commit
gitGraph — cherry-pick and reverse orientation
gitGraph TB:
commit id: "a"
branch topic
checkout topic
commit id: "b"
checkout main
commit id: "c"
cherry-pick id: "b"
Mermaid stress test 5 — models and domains
Diagrams that describe a shape rather than a sequence: data models, requirements, architecture at the C4 level, and the framing diagrams (Cynefin, Ishikawa, Wardley) that mermaid has picked up more recently.
Entity relationship — every cardinality
erDiagram
PROJECT ||--o{ MILESTONE : has
PROJECT ||--o| SERIES : owns
SERIES ||--o{ POST : groups
POST }o--|| AUTHOR : "written by"
BOOK ||--o| SERIES : owns
READER }o--o{ POST : reads
PROJECT {
string slug PK
string title
string status
date updatedAt
}
MILESTONE {
string id PK
string projectId FK
string state
date shippedAt "nullable"
}
POST {
string slug PK
string title
boolean published
}
Requirement diagram
requirementDiagram
requirement sign_in {
id: 1
text: an admin can sign in on every serving host
risk: high
verifymethod: test
}
functionalRequirement same_origin {
id: 1.1
text: the auth handler answers on our own origin
risk: high
verifymethod: test
}
performanceRequirement quiet_navbar {
id: 1.2
text: an anonymous reader triggers no session check
risk: medium
verifymethod: analysis
}
element login_page {
type: page
docref: app/admin/login/page.tsx
}
element middleware {
type: proxy
docref: proxy.ts
}
sign_in - contains -> same_origin
sign_in - contains -> quiet_navbar
login_page - satisfies -> same_origin
middleware - verifies -> quiet_navbar
C4 — context
C4Context
title Portfolio in context
Person(reader, "Reader", "Finds a post, stays for the life pages")
Person_Ext(admin, "Admin", "Writes and publishes")
System(site, "Portfolio", "Next.js on Vercel")
System_Ext(trakt, "Trakt", "Watch history")
System_Ext(github, "GitHub", "Push events")
Rel(reader, site, "reads")
Rel(admin, site, "publishes through the panel")
Rel(site, trakt, "syncs nightly")
Rel(site, github, "syncs nightly")
C4 — container
C4Container
title Portfolio containers
Person(reader, "Reader")
Container_Boundary(site, "Portfolio") {
Container(web, "Web app", "Next.js", "ISR pages and server actions")
Container(cron, "Sync routes", "Route handlers", "Guarded by CRON_SECRET")
ContainerDb(store, "Firestore", "Document store", "Cards, heatmaps, posts")
Container(files, "Storage", "Firebase Storage", "Covers and logos")
}
Rel(reader, web, "reads")
Rel(web, store, "queries at ISR time")
Rel(cron, store, "upserts")
Rel(web, files, "serves images from")
C4 — component
C4Component
title Inside the activity sync
Component(fetch, "Fetchers", "lib/activity.ts", "GitHub and Trakt")
Component(store, "Store", "lib/activity-store.ts", "Delta filter and eviction")
Component(heat, "Heatmaps", "lib/heatmap-store.ts", "Scans activities by scope")
ComponentDb(db, "activities", "Firestore collection")
Rel(fetch, store, "hands cards to")
Rel(store, db, "upserts")
Rel(heat, db, "scans")
Mindmap
mindmap
root((portfolio))
content
blog
posts
series
books
life
anime
steam
screen
music
build
projects
roadmap
pulse
activity
github
trakt
Mindmap — shapes
mindmap
root((the site))
(rounded)
[square]
((circle))
))bang((
)cloud(
{{hexagon}}
Packet diagram
packet-beta
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-105: "Reserved"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
Cynefin
cynefin-beta
title Where a decision sits
complex
"Should the feed group by work or by day?"
"How should the ramp cycle past eight?"
complicated
"Which scope does the heatmap read?"
clear
"Run the migration with a dry run first"
chaotic
"Every diagram is black"
confusion
"Nobody has read the issue yet"
complex --> complicated : "Pattern identified"
chaotic --> clear : "Root cause found"
Ishikawa
ishikawa
Diagrams render unreadable
Colour
A surface seeds the ramp
Tokens pruned from the stylesheet
Theme
darkMode never reaches the palette
Light branch runs in both themes
Library
Values hardcoded past the theme
No variable for a journey label
Process
Screenshots taken without the build
Wardley map
wardley-beta
title How the site is built
size [1100, 600]
anchor Reader [0.95, 0.60]
component "Blog" [0.85, 0.75]
component "Diagrams" [0.70, 0.40]
component "Activity feed" [0.62, 0.55]
component "Firestore" [0.35, 0.85]
component "Vercel" [0.25, 0.90]
Reader -> "Blog"
"Blog" -> "Diagrams"
"Blog" -> "Activity feed"
"Activity feed" -> "Firestore"
"Firestore" -> "Vercel"
Mermaid stress test 6 — grammar diagrams and edge cases
The railroad family, the odds and ends, and then the things that are meant to hurt: unusual characters, absurd labels, directives, and one block that is broken on purpose.
Railroad — EBNF
ISO form — = for assignment, , for concatenation, { } for repetition, and a ; closing every rule. The W3C ::= spelling is not what this parser accepts.
railroad-ebnf-beta
greeting = "hello" , { " " , name } ;
name = "world" | "reader" ;
Railroad — ABNF
Every rule ends in a semicolon here too, which is the part that is easy to miss.
railroad-abnf-beta
greeting = "hello" / "hi";
name = "world";
Railroad — PEG
railroad-peg-beta
Greeting <- "hello" ;
Name <- "world" ;
Railroad — mermaid's own constructors
railroad-beta
expr = sequence(nonterminal("term"), zeroOrMore(choice(terminal("+"), terminal("-"))));
term = terminal("number");
Event modelling
eventmodeling
tf 01 ui EditorUI
tf 02 cmd SavePost
tf 03 evt PostSaved
Info
The smallest diagram mermaid ships — it prints its own version, which makes it a useful canary after an upgrade.
info
Accessibility — title and description
Both should reach the rendered SVG rather than the page.
flowchart LR
accTitle: How a post reaches a reader
accDescr: The editor saves to Firestore, the page is built at ISR time, and the reader is served cached HTML.
Editor --> Firestore --> ISR --> Reader
sequenceDiagram
accTitle: A guarded sync
accDescr {
The cron calls the route, the route checks the secret,
and only then does anything reach the store.
}
Cron->>Route: GET with bearer token
Route->>Store: upsert
Comments inside a diagram
flowchart LR
%% this line is a comment and should not render
A[Visible] --> B[Also visible]
%% B --> C[Commented out]
Init directives
A per-diagram theme override. This one deliberately fights the site's theme — worth knowing whether an author can do that, and what it looks like when they do.
%%{init: {"theme": "forest"}}%%
flowchart LR
A[Forest theme] --> B[Overrides the site]
%%{init: {"flowchart": {"curve": "stepBefore"}}}%%
flowchart LR
A --> B --> C
A --> C
Unicode, emoji and right-to-left text
flowchart LR
A["日本語のラベル"] --> B["Ελληνικά"]
B --> C["العربية"]
C --> D["🎬 emoji 🎧 in 📚 labels"]
D --> E["An em dash — and a ligature fi"]
Very long labels
flowchart TB
A["A label long enough to force the layout engine into a decision about wrapping, which is exactly the decision worth looking at inside a narrow post column on a phone"]
B["Short"]
A --> B
Quotes, brackets and markdown inside labels
flowchart LR
A["A label with 'single' and #quot;double#quot; quotes"]
B["Brackets [square] and (round) and {curly}"]
C["An ampersand and a less-than sign"]
A --> B --> C
flowchart LR
A["`**Bold** and *italic* markdown`"] --> B["`A single line`"]
A tall diagram
Forty rows, to see how a very tall drawing behaves against the post column and the zoom overlay.
flowchart TB
s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 --> s9 --> s10
s10 --> s11 --> s12 --> s13 --> s14 --> s15 --> s16 --> s17 --> s18
s18 --> s19 --> s20 --> s21 --> s22 --> s23 --> s24 --> s25 --> s26
s26 --> s27 --> s28 --> s29 --> s30 --> s31 --> s32 --> s33 --> s34
s34 --> s35 --> s36 --> s37 --> s38 --> s39 --> s40
Two diagrams back to back
No prose between them — the spacing between consecutive diagram cards is its own thing to look at.
flowchart LR
A --> B
flowchart LR
C --> D
A single node, and the smallest mindmap
flowchart LR
A[Alone]
mindmap
root((only a root))
Deliberately broken
This block is malformed on purpose. It should render the error card — not a blank space, not a crash, and not mermaid's own red error graphic.
flowchart LR
A --> --> B
[unclosed
And one that is a real diagram type with nonsense inside it.
sequenceDiagram
Alice ->> Bob: fine
??? not a message at all ???