Block diagrams
A block diagram shows the parts of a system placed on a grid the way the author lays them out: a camera board, a system on chip, a memory map, or a pipeline whose stages sit side by side. Every cell stays where it is written, so the picture keeps the shape a datasheet or a whiteboard gave it. It is for anyone, human or AI agent, who needs a picture where position carries meaning.
TL;DR
| Question | Answer |
|---|---|
| What is it for? | A system drawn as blocks in fixed places: hardware, a board, a memory map, a pipeline. Use a flow diagram when the layout should be chosen for you. |
| How does it start? | block "Title" columns=4, then box id "Label" lines in reading order. Cells fill the grid left to right and wrap at the last column. |
| What goes on the grid? | box (a card or one of six shapes), gap (an empty cell), row (ends a row), group id "Name" { (a grid inside a frame), and arrow (a block arrow). span= makes a cell wider. |
| How are links drawn? | a -> b : "label" draws a square line through the gutters of the grid, never across a box. Two neighbours meet with one straight line. |
| Can I convert Mermaid? | Yes. block-beta and block become a Plotwork block diagram. See From Mermaid. |
| How big may it be? | 200 boxes, 300 links, 12 columns, and groups 3 deep. Past a limit the diagram is refused with error E140, before anything is drawn. |
| How is it drawn? | Each box is a card with its icon on a chip, tinted when it has a tone; each group is a frame with its name in the corner. Layout is plain arithmetic, and the theme chooses every colour, in light and dark. |
Ask your agent
Say what the blocks are, which ones sit together in a row, and which ones hold others. The agent writes the grid.
Use Plotwork to draw our smart camera as a block diagram with four columns. The lens, the image sensor, and the image processor are on the first row, the processor two columns wide. Below them, the system on chip holds the CPU, the neural engine, and the GPU, with the LPDDR5 memory as a cylinder under all three. On the last row put Wi-Fi, USB-C, and a round status light. Link the sensor to the processor with RAW, and the processor to the chip with frames.Use Plotwork to draw the memory map of our microcontroller as a block diagram with eight columns: peripherals across the top, then SRAM and core-coupled RAM, then the bootloader, the application, and the one-time programmable area. Write each address range under its name.Use Plotwork to draw how a request moves through our stack as a block diagram: client, edge, API, and the orders database on one row with block arrows between them, and an arrow down from the API to the event queue.Example
This is the smart camera from the first prompt. It shows a box two columns wide, a group with its own grid of three columns, a cylinder that spans that grid, a gap, a circle, and links with labels that never cross a box.
block "Smart camera" columns=4 desc="A camera's blocks as laid out on the board: the sensor feeds the image processor, which hands frames to the system on chip."box lens "Lens" icon=lucide:scan-eyebox sensor "Image sensor" sub="12 MP"box isp "Image processor" span=2 icon=lucide:cpu tone=bluegroup soc "System on chip" columns=3 span=4 tone=violet icon=lucide:layers { box cpu "CPU" sub="4 cores" box npu "Neural engine" sub="8 TOPS" box gpu "GPU" box ram "LPDDR5" span=3 shape=cylinder icon=lucide:memory-stick}box wifi "Wi-Fi" icon=lucide:wifibox usb "USB-C" icon=lucide:cablegap 1box led "Status light" shape=circle tone=greenlens -> sensorsensor -> isp : "RAW"isp -> soc : "frames"npu <-> ramsoc -> wifiRows:
- Row 1: Lens, Image sensor (12 MP), Image processor (2 columns)
- Row 2: System on chip (group, 4 columns)
- System on chip, on a 3-column grid:
- Row 1: CPU (4 cores), Neural engine (8 TOPS), GPU
- Row 2: LPDDR5 (cylinder, 3 columns)
- System on chip, on a 3-column grid:
- Row 3: Wi-Fi, USB-C, Status light (circle)
Links:
- Lens to Image sensor
- Image sensor to Image processor: RAW
- Image processor to System on chip: frames
- Neural engine and LPDDR5, both ways
- System on chip to Wi-Fi
A memory map
A memory map is a grid read by its widths: each region is as wide as its share of the address space, and a gap keeps a range free. Tones group the kinds of memory. No link is needed, because the position is the meaning.
block "Microcontroller memory map" columns=8 desc="The address space of a small microcontroller, from flash at the bottom to the peripherals at the top."box periph "Peripherals" sub="0x4000 0000" span=8 tone=orange icon=lucide:cablebox sram "SRAM" sub="0x2000 0000, 128 KB" span=3 tone=aqua icon=lucide:memory-stickbox ccm "Core-coupled RAM" sub="64 KB" span=2 tone=aquagap 3box boot "Bootloader" sub="16 KB" span=2 tone=violetbox app "Application" sub="0x0800 4000, 960 KB" span=4 tone=blue icon=lucide:cpubox otp "One-time programmable" span=2 shape=roundRows:
- Row 1: Peripherals (0x4000 0000, 8 columns)
- Row 2: SRAM (0x2000 0000, 128 KB, 3 columns), Core-coupled RAM (64 KB, 2 columns)
- Row 3: Bootloader (16 KB, 2 columns), Application (0x0800 4000, 960 KB, 4 columns), One-time programmable (round, 2 columns)
A request pipeline with block arrows
Block arrows draw a flow the grid already shows, so the stages need no lines between them. dir=both points both ways, dir=down points at the cell below, and row ends a row early. The gaps put the queue under the API.
block "Request pipeline" columns=7 desc="A request passes from the edge to the database, drawn with block arrows between the stages."box client "Client" icon=lucide:monitorarrow a1 "HTTPS" dir=rightbox edge "Edge" sub="CDN and WAF" icon=lucide:shield-check tone=bluearrow a2 dir=rightbox api "API" icon=lucide:server tone=bluearrow a3 "SQL" dir=bothbox db "Orders" shape=cylinder icon=lucide:database tone=aquagap 4arrow a4 "Events" dir=downgap 2rowgap 4box queue "Queue" shape=pill icon=lucide:layers tone=orangeRows:
- Row 1: Client, HTTPS (arrow pointing right), Edge (CDN and WAF), Arrow (arrow pointing right), API, SQL (arrow pointing both ways), Orders (cylinder)
- Row 2: Events (arrow pointing down)
- Row 3: Queue (pill)
The language
A line is one statement. A # starts a comment. Ids are words such as cpu, ram-1 or _x, labels are in double quotes, and options are written key=value. The first line is the header.
The header
block "Smart camera" columns=4 desc="The blocks of a camera board."| Part | Meaning |
|---|---|
block | The kind. |
"Title" | The title. It is the accessible name of the picture and heads the text description. Optional. |
columns= | How many columns the grid has, from 1 to 12. With none, as many as the first row holds, at most 6. |
icons= | auto (the default) gives a box with no icon= the icon its label names, such as a product; off keeps every box plain. |
desc= | A plain-language description for the text description. Optional. A desc "text" statement does the same. |
There is no direction=. The author places every cell, so the picture reads as it was written.
Statements
| Statement | Meaning | Example |
|---|---|---|
box <id> "Label" sub="<text>" icon=<set:name> tone=<tone> span=<n> shape=<shape> | A box in the next cell. sub= is the second line. | box ram "LPDDR5" span=3 shape=cylinder |
gap <n> | An empty cell n columns wide, 1 when no number is written. | gap 2 |
row | Ends the row: the next cell starts a new one. | row |
group <id> "Name" columns=<n> span=<n> tone=<tone> icon=<set:name> {, the cells inside, then } | A group: a grid of its own in a frame, which takes span= columns of the grid around it. The } is on a line of its own. | group soc "System on chip" columns=3 span=4 { |
arrow <id> "Label" dir=<dir> span=<n> tone=<tone> | A block arrow in the next cell. The label is optional. | arrow fwd "Frames" dir=right |
<from> -> <to> : "label" | A link between two boxes, arrows, or groups. The label is optional. | sensor -> isp : "RAW" |
desc "text" | The description of the diagram. | desc "The camera board." |
tone= takes neutral, blue, violet, aqua, orange, green, amber, or red, and icon= takes a name from the closed list of icons, such as lucide:cpu or simple:raspberrypi. A diagram cannot set a colour: the theme chooses every colour, in light and dark.
The grid
Cells fill the grid from the left, in the order written, and wrap at the last column. span= makes a cell as wide as that many columns, and a span that does not fit what is left of the row starts the next row. A span wider than the grid is drawn as wide as the grid, with warning W202.
block "Grid" columns=3box a "One"box b "Two columns" span=2gapbox c "After a gap"rowbox d "A row of its own"The columns are even, so the grid reads as one, unless one wide box would make every column much wider; then each column is as wide as what it holds. A row is as tall as its tallest cell, and the boxes in it grow to match.
Groups
A group is a grid inside a frame, with its name and icon in the corner. Its cells follow on the lines after the {, and it takes span= columns of the grid around it. columns= sets its own grid, and with none it takes as many columns as its first row holds. Groups nest up to three deep, and each level is a shade stronger than the one around it.
block "Camera" columns=4group soc "System on chip" columns=3 span=4 tone=violet icon=lucide:layers { box cpu "CPU" sub="4 cores" box npu "Neural engine" box gpu "GPU"}A link may name a group, and then it ends at the group's frame.
Shapes and block arrows
shape= | Drawn as | Use it for |
|---|---|---|
rect | The Plotwork card, the default | Most blocks |
round | A card with rounder corners | A soft or external part |
pill | A pill | A port, a bus, or a queue |
cylinder | A cylinder | Storage and memory |
circle | A circle at its own size | A light, a sensor, a connector |
diamond | A diamond at its own size | A decision or a switch |
hexagon | A hexagon | A controller or a hub |
Every shape but the circle and the diamond fills its cell, and those two keep their size, centred, so a circle is never stretched into an ellipse. Text wraps inside the shape and never touches its edge.
dir= | The arrow points |
|---|---|
right, left, up, down | One way, at the cell beside it |
both | Left and right |
vertical | Up and down |
A block arrow that points at an empty cell or past the edge of the grid is warning W201.
Links
| Written | Drawn |
|---|---|
a -> b | A solid line with a head at b |
a --> b | A dashed line |
a ..> b | A dotted line |
a <-> b | A line with a head at each end |
a -- b | A line with no head |
A link runs through the gutters between cells with square bends and never crosses a box. Two neighbours in a row or a column meet with one straight line, and the gutter between two neighbours whose link has a label widens to hold the label. Lines that share a gutter keep apart. A label wider than 200px is cut with an ellipsis and warning W203.
Limits and warnings
| Limit | Value | What happens past it |
|---|---|---|
| Boxes and block arrows | 200 | E140 |
| Links | 300 | E140 |
| Columns | 12 | E136 |
| Groups nested | 3 deep | E140 |
| Boxes before the density warning | 40 | W200 |
| Links before the density warning | 30 | W200 |
| A label | Three lines | Cut with an ellipsis, and W203 |
| A link label | 200px | Cut with an ellipsis, and W203 |
The limits are checked from the text alone, so a diagram that is too big is refused at once with a hint on how to split it. The layout is plain arithmetic over the grid, so a diagram of 40 boxes is laid out in a few milliseconds.
| Code | Severity | When | Fix |
|---|---|---|---|
E100 | error | A missing id or label, a group with no {, text after a }, a link from a box to itself, or a diagram with no box. | Each says what to write. |
E110, E121, E130, E131, E133, E134, E135, E136 | error | An unknown statement or tone, a duplicate id, an unknown box in a link, an unclosed or unmatched group, an unknown option, or a bad span, column count, shape, gap, or arrow direction. | Each says what to write, with the nearest name for a mistyped one. |
E140 | error | The diagram is over a limit in the table above. | Split the diagram. |
W200 | warning | More than 40 boxes or 30 links. | Split the diagram, or place boxes that talk side by side. |
W201 | warning | A group holds no box, a block arrow points at nothing, or a link between neighbours has to go round. | Fill or remove the group, turn the arrow, or move what is in the way. |
W202 | warning | A span is wider than its grid, or the picture is wider than a column keeps readable. | Lower the span, use fewer columns, or shorten the labels. |
W203 | warning | Text was cut with an ellipsis. | Shorten the text, or move detail into sub=. |
From Mermaid
Mermaid block-beta and block convert to a Plotwork block diagram that keeps the grid: the columns, the widths, the spaces, and the composite blocks. Ask your agent to convert it, or use the convert_mermaid tool. The migration guide covers the converter in full.
block-beta columns 3 a["Frontend"] b["Backend"]:2 block:data:3 columns 2 db[("Orders")] cache(("Cache")) end a --> b b -- "SQL" --> db| Mermaid | Plotwork |
|---|---|
columns 3 | columns=3 on the header, or on the group inside a composite. columns auto lays the blocks on one row. |
a["Label"]:2 | box a "Label" span=2 |
space, space:3 | gap, gap 3 |
block:id:2 and its blocks, then end | group id "id" span=2 {, its boxes, then } |
a("x"), a(["x"]), a[("x")], a(("x")), a{"x"}, a{{"x"}} | shape=round, pill, cylinder, circle, diamond, hexagon |
a[["x"]], a>"x"], a[/"x"/], a[\"x"\], a((("x"))) | The nearest shape, a plain box or a circle, with M204 |
a<["x"]>(right), (x), (y) | arrow a "x" dir=right, dir=both, dir=vertical |
a --> b, a --- b, a <--> b, a -.-> b | a -> b, a -- b, a <-> b, a ..> b |
a-- "X" -->b, a -->|X| b | a -> b : "X" |
style, classDef, class, :::name | A fill that has a tone becomes tone= (M204, or M207 for a class); everything else is dropped with M200. |
See also
| Doc | Why |
|---|---|
| Writing diagrams | The flow, sequence, and schema kinds, and the options every kind shares |
| Layered architecture | Rows of blocks inside named tiers, for a stack of layers |
| Migrating from Mermaid | The converter, its diagnostic codes, and what carries over |
| Icon reference | Every icon name you can put in icon= |
| Language reference | Every word of the language, one page for each topic |