Why this deep dive exists
The main six sessions covered the daily drivers. This deep dive is the specialty shelf: four types you'll reach for maybe once a month - and when you do, nothing else will do the job. Honest framing up front: three of the four carry a -beta suffix, which means the syntax can still shift between versions. Use them for docs you control, keep the examples modest, and enjoy them - they are some of the most charming corners of mermaid. All four get a Nova workout below.
block-beta: when auto-layout fights you 8 min
Flowcharts let dagre decide where boxes go - usually a gift, occasionally a wrestling match. Block diagrams flip the deal: you declare a grid of columns and place every block yourself. Perfect for the tidy "poster" view of a platform where the POSITION is the message: sources on the left, platform in the middle, consumers on the right.
Self-studyThe grid: columns, spans, space3 min▶
Three ideas run the whole show. columns N sets the grid width; blocks fill it left to right, wrapping to new rows. A suffix like :2 makes a block span columns. And space (or space:2) is an invisible block - your alignment tool.
block-beta columns 3 a["Sources"] b["Platform"] c["Consumers"] d["Batch lane"]:2 e["Stream lane"] space f["You choose the grid"] space
- Row wrapping is automatic: with
columns 3, the 4th block starts row two. Count as you write. - Spans eat columns:
d["Batch lane"]:2takes two cells, so only one cell remains in that row. - Shapes carry over from flowcharts:
x[("db")]cylinder,x(["pill"]),x{"decision"}all work here. - Nesting:
block:ID ... endmakes a composite block containing its own mini-grid - a group border without a subgraph.
Self-studyNova as a tidy 3-column poster3 min▶
The classic use: a platform poster where column one is sources, column two is the platform, column three is consumers. Edges still exist (-->, with labels as a-- "text" -->b), but layout no longer reflows when you add one - the grid holds.
block-beta
columns 3
hdr["Nova data platform"]:3
ev["App events"] ing["Ingestion"] bi["Dashboards"]
crm["CRM export"] qa["Quality checks"] ml["ML features"]
space dw[("Warehouse")] space
ev --> ing
crm --> ing
ing --> qa
qa-- "pass" -->dw
dw --> bi
dw --> ml
style hdr fill:#FFD9E6,stroke:#D6246E
A platform team kept redrawing their "what we own" slide every quarter because the flowchart version reshuffled itself whenever a box was added. Rebuilt as block-beta, the grid never moves: new services drop into their column, the poster stays recognizable, and executives stop asking "why does the diagram look different this time?"
Self-studyGotchas1 min read▶
- Beta: current docs have started writing plain
block; bothblockandblock-betaparse in v11. This page usesblock-beta, which works across all v11 releases. - Arrows don't route politely. Edges draw fairly straight lines between cells - if they cross a block, rearrange the grid, not the edge.
- Never name a block
end- it closes composite blocks. Same reserved-word trap as flowcharts. - Miscounted rows are the #1 bug: a forgotten
spaceshifts everything after it one cell left. When the poster looks drunk, count cells per row first.
packet-beta: bytes, drawn like an RFC 6 min
Packet diagrams draw bit-level field layouts - the picture you've seen in every TCP textbook. Niche? Extremely. But if you ever document a binary event envelope, a fixed-width file format, or a wire protocol, this type produces in six lines what would take an hour in a drawing tool.
Self-studyNova's event envelope, bit by bit3 min▶
Each line is start-end: "Field name" in bit positions; rows wrap every 32 bits automatically. Since v11.7 you can also write +8: "Field" and let mermaid count on from wherever the previous field ended - much kinder when a design is still moving.
--- title: "Nova event envelope (header)" --- packet-beta 0-7: "Version" 8-15: "Event type" 16-31: "Tenant ID" 32-63: "Event timestamp" 64-95: "User ID hash" 96-111: "Payload length" 112-127: "Checksum"
- Ranges are inclusive:
0-7is eight bits. Off-by-one here means your doc lies about the wire format. - Auto-counting:
+16: "Tenant ID"starts where the previous field stopped; you can mix+nand explicit ranges freely. - Single bits: just
106: "ACK"- one number, no range. Great for flag bits.
Self-studyGotchas1 min read▶
- Beta: introduced v11.0 as
packet-beta; current docs write plainpacket. Both parse in v11 - this page sticks with the widely compatible form. - Gaps are errors: fields must be contiguous. Skip bits 40-47 and the parser complains - pad with a "Reserved" field like real RFCs do.
- It only does layout, not meaning: no types, no endianness, no units. Put those in a table next to the diagram.
- Long labels squeeze: a 4-bit field with a 30-character name gets unreadable. Abbreviate, expand in prose.
treemap-beta: proportions you can feel 6 min
A treemap tiles nested rectangles sized by value - hierarchy AND magnitude in one picture. For a data person this is the "where does it all go?" diagram: storage by domain, cost by team, rows by table. The syntax is the simplest on this page: indentation is the hierarchy.
Self-studyNova's warehouse storage by domain3 min▶
Quoted names are nodes; indentation nests them; "Leaf": value sets the size. That's the whole grammar. Tag a node with :::class and style it with a classDef - handy for pointing at the elephant.
treemap-beta
"Nova warehouse (GB)"
"Events domain"
"Page views": 420:::hot
"Clicks": 310
"Sessions": 120
"CRM domain"
"Accounts": 80
"Contacts": 60
"ML features"
"Feature store": 150
"Training sets": 90
classDef hot fill:#D6246E,color:#FFEFF5,stroke:#8E1146;
- Parents don't take values - they sum their children. Give a parent its own number and the picture stops being trustworthy.
- valueFormat (frontmatter config) formats numbers with d3 specifiers:
'$0,0'for cost treemaps,'.1%'for shares. - Depth discipline: two levels read instantly, three is the ceiling. Deeper than that, link out to a second treemap.
The fastest storage-cost conversation ever: a treemap of warehouse GB by domain in the platform README. Finance saw in one glance that one event table dwarfed everything else combined - a conversation that three months of spreadsheet tabs had failed to start.
Self-studyGotchas1 min read▶
- Genuinely new: the docs warn the syntax "may evolve in future versions". Fine for living docs; risky for anything you'll print and frame.
- Indentation is load-bearing - a leaf indented one level too far silently changes the hierarchy. Diff carefully.
- Tiny values vanish: a 2 GB slice next to a 420 GB slice renders as a sliver with no readable label. Group small stuff into "Other".
- No negatives - treemaps size by area, and negative area isn't a thing.
- Cousin worth knowing: a venn diagram type also exists in recent releases - even newer than treemap, so we mention it and move on. Watch the release notes.
requirementDiagram: promises, traced 8 min
The grown-up of this page (no beta suffix): a SysML-style diagram that connects requirements to the things that satisfy and verify them. For a data team, read "requirement" as data quality SLA and "element" as pipeline component - suddenly your DQ policy has a picture, with risk levels and verification methods built into the grammar.
Self-studyNova's data quality requirements, formally traced4 min▶
Two building blocks. A requirement has an id, text, a risk (low, medium, high) and a verifymethod (analysis, inspection, test, demonstration). An element is anything real - a DAG, a test suite, a doc. Relationships connect them: {source} - <type> -> {destination} where type is one of contains, copies, derives, satisfies, verifies, refines, traces.
requirementDiagram
requirement freshness {
id: "DQ-1"
text: "Warehouse tables refresh within 60 minutes"
risk: high
verifymethod: test
}
functionalRequirement no_null_ids {
id: "DQ-2"
text: "Customer ID is never null after ingestion"
risk: medium
verifymethod: inspection
}
element quality_checks {
type: "dbt test suite"
docref: "nova/dbt/tests"
}
element ingestion_job {
type: "Airflow DAG"
docref: "nova/dags/ingest"
}
quality_checks - verifies -> freshness
ingestion_job - satisfies -> no_null_ids
freshness - traces -> no_null_ids
- Six requirement flavors:
requirement,functionalRequirement,interfaceRequirement,performanceRequirement,physicalRequirement,designConstraint. For DQ work the first two carry most of the load. - satisfies vs verifies is the useful distinction: the ingestion job SATISFIES the rule (it does the work); the test suite VERIFIES it (it proves the work happened).
- Quote free text - names, text and docrefs can go unquoted, but the parser fails if it smells a keyword. Quotes end the guessing.
Self-studyGotchas1 min read▶
- Layout is take-it-or-leave-it: big requirement webs get tangled. Split by domain (one diagram per data product) before you hit ten nodes.
- The enums are closed lists -
risk: criticalis a parse error. Map your own severity scale onto low/medium/high. - The arrow is fussy: it's
- satisfies ->with single hyphens, not the flowchart's-->. Muscle memory will betray you exactly once per session. - It documents intent, not status - nothing turns red when a test fails. Pair it with your observability stack; this is the map, not the alarm.
Try it yourself - this week ◐ 30-40 min total
- Rebuild YOUR platform as a block-beta poster: 3 columns, sources / platform / consumers, one spanning header. Compare it honestly with the flowchart version - which one goes in the exec deck?
- Take any binary or fixed-width format you touch (an event header, a legacy file feed) and packet-beta it. If you can't fill every bit, you've just found undocumented bytes - that's the exercise working.
- Treemap your warehouse: pull row counts or GB by schema from your catalog, two levels deep, tag the biggest table with a classDef. Post it where finance can see it.
- Write three real data quality requirements as a requirementDiagram, each with an element that satisfies it and one that verifies it. If nothing verifies a requirement, that's a gap - the diagram just did governance work.
- Skim the release notes for the venn type before using it anywhere real - it's newer than everything on this page.
Official docs covered
This deep dive works through these sections of the official docs at mermaid.js.org (mermaid 11.x). Beta types are marked - expect their syntax to keep evolving.
Three questions before you go 🎯 ◐ 90 seconds
1 · In a block-beta grid with columns 3, how do you make one block span two columns?
The :n suffix sets the span - and space:n does the same for invisible spacer blocks. Count your cells per row after adding one.
2 · In packet-beta, which line adds a 16-bit field that starts wherever the previous field ended?
+n auto-continues from the previous field (v11.7+). Option A would declare a single flag bit at position 16 - a very different claim about your bytes.
3 · Which line correctly connects Nova's dbt suite to a requirement in requirementDiagram?
Single hyphens around the relationship type: source - type -> destination. The double-dash flowchart arrow is the classic mistake here.