Blog
About

© 2026 Uzair Tariq

← Back to blog

Mermaid Test Post 4

August 29, 2026

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

Drawing

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

Drawing

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

Drawing

Timeline

timeline
  title History of the site
  2023 : first deploy
  2024 : blog : books
  2025 : activity feed : heatmaps
  2026 : projects : diagrams : the ramp

Drawing

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

Drawing

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

Drawing

Kanban

kanban
  Todo
    [Write the post]
    [Fix the sync]
    [Answer the issue]
  Doing
    [Ship diagrams]
  Blocked
    [Wait on upstream]
  Done
    [Ramp tokens]
    [Theme sweep]

Drawing

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 }

Drawing

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"

Drawing

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

Drawing

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"

Drawing

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
  }

Drawing

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

Drawing

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")

Drawing

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")

Drawing

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")

Drawing

Mindmap

mindmap
  root((portfolio))
    content
      blog
        posts
        series
      books
    life
      anime
      steam
      screen
      music
    build
      projects
        roadmap
        pulse
      activity
        github
        trakt

Drawing

Mindmap — shapes

mindmap
  root((the site))
    (rounded)
      [square]
      ((circle))
    ))bang((
      )cloud(
    {{hexagon}}

Drawing

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"

Drawing

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"

Drawing

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

Drawing

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"

Drawing

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" ;

Drawing

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";

Drawing

Railroad — PEG

railroad-peg-beta
Greeting <- "hello" ;
Name <- "world" ;

Drawing

Railroad — mermaid's own constructors

railroad-beta
expr = sequence(nonterminal("term"), zeroOrMore(choice(terminal("+"), terminal("-"))));
term = terminal("number");

Drawing

Event modelling

eventmodeling

tf 01 ui EditorUI
tf 02 cmd SavePost
tf 03 evt PostSaved

Drawing

Info

The smallest diagram mermaid ships — it prints its own version, which makes it a useful canary after an upgrade.

info

Drawing

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

Drawing
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

Drawing

Comments inside a diagram

flowchart LR
  %% this line is a comment and should not render
  A[Visible] --> B[Also visible]
  %% B --> C[Commented out]

Drawing

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]

Drawing
%%{init: {"flowchart": {"curve": "stepBefore"}}}%%
flowchart LR
  A --> B --> C
  A --> C

Drawing

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"]

Drawing

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

Drawing

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

Drawing
flowchart LR
  A["`**Bold** and *italic* markdown`"] --> B["`A single line`"]

Drawing

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

Drawing

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

Drawing
flowchart LR
  C --> D

Drawing

A single node, and the smallest mindmap

flowchart LR
  A[Alone]

Drawing
mindmap
  root((only a root))

Drawing

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

Drawing

And one that is a real diagram type with nonsense inside it.

sequenceDiagram
  Alice ->> Bob: fine
  ??? not a message at all ???

Drawing