drawspec

Declarative diagram spec to clean, themeable SVG. Thirteen diagram kinds, no coordinates in the format, writable by an LLM.

View the Project on GitHub nuncaeslupus/drawspec

The document format

A document is JSON. It says what the diagram means — the nodes, the edges, the words, and a semantic role for each — and it carries no coordinate, no size and no colour, because those are the tool’s output and never its input. The refused fields at the end of this page are that rule made mechanical.

Every document declares "version": 1 and one of the 36 kinds. The machine-readable form of this page is the published JSON Schema, https://nuncaeslupus.github.io/drawspec/schema/drawspec-v1.schema.json — point an editor at it with a $schema key and get completion and inline validation for free.

{ "$schema": "https://nuncaeslupus.github.io/drawspec/schema/drawspec-v1.schema.json", "version": 1, "kind": "flow", "nodes": [] }

drawspec validate doc.json prints every violation with the JSON pointer of the place it was written, so one pass over its output is one edit.

Every document

These fields are legal whatever the kind is.

Field Type Required What it is
$schema string no Optional, and only for editors: the URL of this schema.
version integer yes ‘version’ is required. Declare it so a future format change is a loud failure rather than a misread document.
kind string — one of flow, tree, cycle, stack, timeline, columns, matrix, pyramid, rings, funnel, chart, quadrant, scatter, curve, files, states, sequence, lanes, entities, gantt, board, fishbone, venn, journey, treemap, sankey, numberline, barmodel, waterfall, pie, mindmap, argument, familytree, meter, rag, clock yes Which of the thirty-six diagrams this is. It selects the fields that are legal below, so it is the first thing to get right.
title string no The diagram’s accessible name.
description string no The diagram’s accessible description.
caption string no A line of text belonging to the whole diagram rather than to any one element — an axis’s units, a condition that holds throughout, the sentence the original wrote alongside the figure. Drawn outside the drawing; the theme’s [canvas] caption says above or below. Use a note for something attached to one element.
width number, greater than 0 no Overrides the theme’s canvas width. Binding.
height number, greater than 0 no Advisory unless height_binding is true.
height_binding boolean no Makes height a constraint rather than a hint.
theme string no A bundled theme name or the path of a theme file. A relative path is read from the document’s own folder when the file is there, so a theme can sit beside the diagrams that use it.

What each kind adds

The kind selects a family, and the family selects which further fields are legal. A field belonging to another family is refused by name rather than ignored — a chart with nodes in it is a mistake worth hearing about.

flow, tree, cycle

Field Type Required What it is
nodes array of node, at least 1 yes The boxes. Order is not a coordinate — the layout decides where a box goes — but it is the order siblings are drawn in: where nothing else separates two boxes of the same rank, they read in the order written here.
edges array of edge no What connects to what. A tree takes one edge per child.
groups array of group no Boxes drawn around sets of nodes, each with its own caption.
bands array of band no Named things that run alongside a set of boxes rather than containing them — drawn as a labelled bar beside the boxes they accompany. For the activity that goes on throughout: a source sheet with one continuous concern above its steps and another below says the steps are surrounded by them, and two such bands are peers. A group cannot say that — a box sits inside one container or none, so two groups over the same members had to be nested, which draws a hierarchy that is not there.

flow, tree

Field Type Required What it is
classes array of class, at least 1 no The classes the boxes are sorted into, each {id, text}: 1 to 4, every one used by some node. Each is drawn as a faint fill from the theme’s fixed sequence ([classes] fills: a grey wash, then patterns), in the order declared, and the key under the drawing names each by its text. For a grouping the reader must see across the whole drawing — external systems greyed in a C4 context, steps by owning team.

flow

Field Type Required What it is
loops array of loop no The feedback loops of a causal loop diagram, each named and marked R (reinforcing) or B (balancing) inside the loop it closes — the type derived from the signs, never chosen. Needs polarity on the edges.

cycle

Field Type Required What it is
hub hub object no What the loop turns around: the system a quality cycle improves, the model a data flywheel retrains. Not a step — it is drawn in the middle of the ring, outside the check that the ring closes through every node. An edge may join it to a step only as a spoke, in the roles ‘aside’, ‘weak’, ‘link’: a solid arrow to the middle would read as one more step. Needs a ring of at least 3 steps.

stack, timeline, columns

Field Type Required What it is
items array of item, at least 1 yes The entries, in the order they are meant to be read: down for stack, along for timeline and columns.

columns, timeline

Field Type Required What it is
rise boolean no Whether the series ascends: each entry drawn taller than the one before it, all sitting on a common baseline — the canvas floor for columns, the axis itself for timeline. For a scale where the order is the content and not merely the reading direction — five levels of open data, three degrees of a change — and where equal entries say they are peers, which is the opposite. The author says the series rises; the theme’s [box] rise says by how much, so there is no per-column height to get wrong. Not a pyramid: that draws the last level as the narrowest, which is the right shape for a maturity model and the wrong one for a ladder.

timeline

Field Type Required What it is
spans array of span no Named intervals between two entries, drawn as bars under the axis. For the quantity that is not a thing on the diagram but the distance between two things on it: a recovery objective is not an event, it is how much lies between the last backup and the disaster.

matrix

Field Type Required What it is
cells array of cell, at least 1 yes What is in the grid. A cell states where it starts, not where it is drawn.
columns array of string no Column headings, left to right. Omit for a matrix with none.
rows array of string no Row headings, top to bottom.
edges array of edge no What connects to what, between cells that carry an id. The cells of a grid are not always only cells: one may produce another, or come before it. The grid places them; the relations are a separate thing, and without them a reader sees a table where the source drew a process.
scale array of string, at least 2 no Says the groups are ordered, and in what order: 2 to 5 group names, weakest first — ["rare", "sometimes", "often"]. For a heatmap, a risk matrix, a skills matrix: a grid whose cells say how much. The cells are then filled by tone, light to dark, from the theme’s [mark] ramp instead of with unrelated patterns, and the key lists every step in this order (with key texts where given). Every cell group must be one of these; a cell with no group stays blank, for not assessed. Names, not numbers: the author buckets the values.
key array of key no What each group of cells is called, for the key drawn under the grid. Without one, a group is announced to the reader under the name the cells use for it — which is fine when that name is a name, and is how an id-shaped key like carrega ends up as visible text.

pyramid

Field Type Required What it is
levels array of level, at least 1 yes Apex first. The widest band is the last one written.

rings

Field Type Required What it is
rings array of ring, at least 1 yes Innermost first, working outwards.

funnel

Field Type Required What it is
stages array of stage, at least 1 yes Widest first: a funnel is a pyramid lying down.
unit string no What the stages’ amounts count — visitors, applications, £k — written after each one. Only with amounts.
values boolean no false leaves the amounts and shares out and writes the stage names alone. Defaults to true.

chart

Field Type Required What it is
axes axes object yes Both axes. An unlabelled axis cannot be read, so both are required.
series array of series, at least 1 yes What is plotted. More than one gets a legend.
values boolean no Whether to write each point’s own number on the drawing. Defaults to true; set false for a chart whose shape is the message and whose numbers would be noise.

quadrant

Field Type Required What it is
axes axes-quadrant object yes The two named axes whose crossing makes the four quadrants.
quadrants array of string no Exactly four names, one per quarter, written faint in its outer corner: top right first, then counter-clockwise — top left, bottom left, bottom right (Mermaid’s order). An empty string leaves that quarter unnamed.
positions array of position, at least 1 yes The items placed in the plane, each by what it scores, not by where it goes.

files

Field Type Required What it is
root string no The folder everything is in, drawn as the top row. Omit it for a listing with several top-level entries and no common parent.
entries array of entry, at least 1 yes The paths, one per entry. Siblings keep the order written here.
sort string — one of given, name, folders-first no How siblings are ordered: given (the default) keeps the order written, name sorts naturally (file2 before file10), folders-first sorts by name with folders above files. A ... row stays last.
style string — one of icons, plain, unicode, ascii no icons (the default) draws folder and file pictures; plain draws the names and guides only; unicode and ascii draw the tree as monospace text, with box-drawing or plain ASCII branches.

states

Field Type Required What it is
states array of state, at least 1 yes The conditions the machine can be in. A newline in text is a lead and a detail, as everywhere: the state’s name over what holds in it. Every state must be reachable from initial.
initial string yes The state the machine starts in, drawn as a filled dot with an arrow to it. Required: reachability is measured from here. May name a group, which must then say its own initial.
final array of string no The states the machine ends in, each drawn with an arrow to a ringed dot. A final state has no outgoing transition.
transitions array of transition no What moves the machine from one state to another, each labelled event [guard] / action from its own fields.
groups array of composite no Composite states: a frame around the states inside it, named at its corner. Groups may nest. A transition from a group leaves it from any state inside; one to a group enters it at the group’s initial. A composite with regions is drawn divided by dashed lines, every region current at once.

sequence

Field Type Required What it is
participants array of participant, at least 2 yes Who takes part, drawn left to right in the order written, each a head with a dashed lifeline under it. The order is the reading order, not a coordinate. Every participant must send or receive a message. A person taking part is role: "actor", drawn as the UML stick figure with the name under it.
messages array of message, at least 1 yes What is said, drawn top to bottom in the order written: the order is the diagram. A call (flow) answered later by a weak reply opens an activation bar on the receiver from the call’s row to the reply’s; nobody writes how tall it is. An async message (solid line, open head) is sent without waiting, opens no bar and takes no reply.
fragments array of fragment no Frames round a run of messages, from to to, and every participant they touch. Fragments nest or are apart; one that starts inside another and ends outside it is refused.
groups array of group no A frame round a run of neighbouring lifelines, named at its top — inside our account. Members must be next to each other in participants, and a participant is in one group or none.

lanes

Field Type Required What it is
nodes array of lane-node, at least 1 yes The steps, each in the lane its actor names. Ranked along the lanes as a flow is; within one lane, order is the order siblings are drawn in.
edges array of edge no What follows what, as on a flow. An edge between two lanes crosses the boundaries between them: that crossing is the hand-off.
lanes array of string, at least 1 no The lanes in order — top to bottom when they run across the page, left to right when they run down it; the theme decides which. Each must be some node’s actor, spelled exactly, and every actor must be listed. Omit it and the lanes come in the order their actors first appear in nodes. At most 6.
phases array of phase, at least 2 no The stages the process passes through, in the order it runs — named in a band along the lanes’ edge and divided by faint lines across every lane (a cross-functional flowchart’s phases). Each phase lists its steps, and with phases given every step is in exactly one. A phase’s steps are drawn after every step of the phases before it, so the phases never interleave. 2 to 6.
classes array of class, at least 1 no The classes the boxes are sorted into, each {id, text}: 1 to 4, every one used by some node. Each is drawn as a faint fill from the theme’s fixed sequence ([classes] fills: a grey wash, then patterns), in the order declared, and the key under the drawing names each by its text. For a grouping the reader must see across the whole drawing — external systems greyed in a C4 context, steps by owning team.

entities

Field Type Required What it is
entities array of entity, at least 1 yes The boxes: each a name (and a stereotype), a rule, its fields, and its operations under a second rule. Placed by their relations: general above specific when there is a hierarchy, side by side otherwise.
edges array of relation no The relations between entities, each landing on a box — or, with from_field / to_field, on one row of it — and carrying a cardinality at either end. A hierarchy may not loop.

gantt

Field Type Required What it is
axis axis-gantt object yes The one axis the plan runs along: what its numbers count, in a unit you name. There are no dates.
tasks array of task, at least 1 yes One row each, in the order written — that order is the reading order. start and end make a bar; at makes a milestone.
groups array of group no Phases, each a run of consecutive tasks, drawn as a heading row with a bracket over the phase’s span. With groups, every task is in one.
edges array of dependency no Finish-to-start dependencies between tasks: drawn from the end of from into the start of to.
marks array of mark no Named points in time — today, a deadline, a freeze — each a line across every row with its name above.

board

Field Type Required What it is
columns array of board-column, at least 1 yes Left to right as written: states on a kanban board, prompts on a retrospective, the steps of a story on a story map. All one width.
rows array of slice, at least 1 no Slices across every column, top to bottom — the releases of a story map. With rows, every card names one.
cut string no The id of a row: a heavy rule is drawn under it — everything above ships first. Not the last row, which has nothing below it to cut from.
cards array of card, at least 1 yes Each in a column (and a row, with rows). Within a cell they stack in the order written, top-aligned, so a short column looks short.

fishbone

Field Type Required What it is
effect effect object yes The observed problem, stated as a fact: drawn in the head box at the end of the spine, always as the diagram’s emphasis.
categories array of category, at least 2 yes The bones, drawn alternately above and below the spine, nearest the head first: the written order is the reading order from the head outwards.

venn

Field Type Required What it is
sets array of venn-set, at least 2 yes Two to four sets, each a circle of one size with its name outside it — four are four equal ellipses, so all fifteen regions exist. Not sizes: the shapes are equal, because a Venn diagram says what overlaps, not how much.
regions array of region no What each region holds, named by membership. A region not listed is drawn empty: its set’s name says enough.

journey

Field Type Required What it is
feelings array of string, at least 2 yes The named levels a stage’s feeling may take, worst first: drawn as guides across the map, the worst at the bottom, each named once on the left. Names, not scores.
rows array of journey-row, at least 1 no The detail rows under the feeling line, top to bottom: what the person does, where, what gets in the way. Optional: without rows the map is the stages and the line.
stages array of journey-stage, at least 2 yes Left to right as written, one column each, all one width. The feeling line passes through every stage’s point.

treemap

Field Type Required What it is
parts array of treemap-part, at least 2 yes The parts of one total, each a rectangle whose area is in proportion to its amount, with its words inside it. Laid out largest first whatever the written order, which only breaks ties; note parts go last.
groups array of treemap-group, at least 1 no One level of grouping: each group is a captioned frame holding the parts that name it, filled with the theme’s mark fills in the order written. Groups do not nest.
unit string no What the values are in — kB, GB, hours — written after each one.
values boolean no Whether to write each part’s amount under its words, and each group’s total beside its name. Defaults to true.

sankey

Field Type Required What it is
nodes array of sankey-node, at least 2 yes Where the quantity starts, passes and ends. A node’s column is derived from the flows — sources left, ends right — never written; the written order is where the order down each column starts.
flows array of sankey-flow, at least 1 yes How much goes from one node to another, each a band whose thickness is in proportion to its amount. What reaches a node in the middle must all leave it, and nothing flows back.
unit string no What the amounts are in — tickets, cores, € million — written after each total.
values boolean no Whether to write each node’s total under its name. Defaults to true.

numberline

Field Type Required What it is
axis axis-numberline object yes The one scale, drawn across the canvas with an arrowhead at each end: numbered ticks, or two named ends.
points array of numberline-point no Values marked on the axis, each a dot with its words above it — or below the numbers, with a leader, when the words above would touch.
ranges array of numberline-range no Stretches of the scale, each a line in its own track above the axis, in the order written — the last nearest the axis. Each end is closed, open, or missing: a range with no to runs on past max.

barmodel

Field Type Required What it is
bars array of barmodel-bar, at least 1 yes One to three bars, top to bottom, all starting at one left edge, every length in one scale: the longest bar fills the width.
braces array of barmodel-brace no What a stretch adds up to — the whole, a difference, a total over two bars — each a brace with its amount or its ?.

waterfall

Field Type Required What it is
axis waterfall-axis object yes The vertical axis: its label, what the numbers are and their unit.
bars array of waterfall-bar, at least 3 yes The bars, left to right: a total first, signed amount steps, any subtotals (a total mid-way, checked against the running sum), and a total last.

argument

Field Type Required What it is
claim string yes The contention, drawn at the top in the heavy outline. Points name it as "on": "claim". A qualifier (probably, in most cases) is a word in it.
points array of argument-point, at least 1 yes Every reason, objection, rebuttal and piece of evidence, each on the box it bears on, for or against it. Drawn as a tree down from the claim, siblings in the order written; at most 15, and 4 deep.

familytree

Field Type Required What it is
people array of familytree-person, at least 2 yes Everyone in the tree. Generations and numbers are derived: a child is one row below its parents, a partner shares their partner’s row, and people are numbered left to right in each row (II-3). At most 30, in 4 generations.
couples array of familytree-couple, at least 1 yes Who partnered whom, and their children. Everyone is in at least one couple, as a partner or a child.

meter

Field Type Required What it is
style string — one of bar, thermometer, dial, bullet no How every meter in the document is drawn: bar (the default, a progress bar), thermometer (a goal filling up), dial (a needle on a half-circle) or bullet (a bar on named bands, with a target tick). One for the whole panel, so like is compared with like.
meters array of meter-meter, at least 1 yes The meters, 1 to 6, in reading order: rows for bars and bullets, columns for thermometers, up to three dials to a row. Each has its own scale.

clock

Field Type Required What it is
clocks array of clock-face, at least 1 yes The faces, 1 to 12, in reading order, up to four to a row: each a time, and optionally a text under it and a since.
numerals string — one of arabic, roman, quarters, none no The numbers round every face: arabic (the default, 1 to 12), roman (I to XII), quarters (12, 3, 6 and 9 only) or none.
readout string — one of words, digits, both, none no What is written under each face: words (the default: quarter past three), digits (3:15, as written), both, or none for a worksheet.

rag

Field Type Required What it is
rows array of rag-row, at least 1 yes The workstreams or risks, 1 to 15, in the order written: each a name, its rag, and optionally a trend and a note.

mindmap

Field Type Required What it is
centre string yes The topic: the one strongly boxed element, in the middle of the map. Every main branch is a peer round it.
branches array of mindmap-branch, at least 2 yes The main branches, 2 to 8, placed clockwise from the top right in the order written and split between the two sides so they balance: the first is always on the right. Nested, up to three levels, 30 branches in all; the nesting is the structure, so there are no edges.

pie

Field Type Required What it is
parts array of pie-part, at least 2 yes The parts of one total, 2 to 8, clockwise from twelve o’clock in the order written (a note part last), each labelled with its text and amount — inside its sector, or beside it on a leader line.
unit string no What the amounts are in — pupils, £m, % — written after each one. With % the amounts must add up to 100, within one point of rounding.
values boolean no false leaves the amounts out and writes the names alone.

scatter

Field Type Required What it is
axes axes-continuous object yes Both axes, each read as a measurement — unlike quadrant’s.
positions array of position, at least 1 yes The points, each placed by its two measured values.

curve

Field Type Required What it is
spans array of span no Named distances between two waypoints, drawn as a capped line with the name beside it. For the quantity that is the gap itself: a cost variance is not a point on the drawing, it is how far one curve is from another, and a caption saying so states it without showing it. Either way round — two waypoints at one moment measure vertically, two at one value measure along.
axes axes object yes Both axes. A named shape still needs saying what it is a shape of.
curves array of curve, at least 1 yes The shapes drawn, each through its own waypoints.

The readability budget

A document that would draw can still be refused for holding too much to read. Each kind has a budget — the most entries its counted arrays may hold — and a document past it is refused with the pointer of the first entry over, before any layout is tried. It is not the fit limit: a fit refusal says the canvas is too small, and arrives later, around twenty boxes. This says the picture would be searched rather than read.

The remedy is to split: an overview that names each part once, plus a detail diagram per part, each within the budget. There is no opt-out — the top-level width and height size the canvas, and a wider canvas does not make the drawing easier to take in. Every number below sits above the largest reference document of its kind, so nothing in the gallery is refused.

Kind At most
flow 15 nodes, 16 edges, 6 loops, 4 classes
tree 15 nodes, 4 classes
cycle 8 nodes
stack 10 items
timeline 10 items
columns 6 items
matrix 25 cells
pyramid 7 levels
rings 6 rings
funnel 7 stages
chart 6 series
quadrant 12 positions
scatter 20 positions
curve 4 curves
files 30 entries
states 14 states, 24 transitions, 4 regions per group, 4 states that are fork or join
sequence 8 participants, 30 messages
lanes 15 nodes, 16 edges, 6 lanes, 6 phases, 4 classes
entities 8 entities, 12 edges, 12 fields per entity, 8 operations per entity
gantt 16 tasks, 20 edges, 4 marks
board 6 columns, 4 rows, 32 cards, 8 cards per cell
fishbone 6 categories, 5 causes per category
venn 4 sets, 15 regions
journey 7 stages, 5 feelings, 4 rows
treemap 10 parts, 4 groups
sankey 14 nodes, 24 flows
numberline 15 points, 4 ranges
barmodel 3 bars, 8 parts per bar, 6 braces
waterfall 12 bars
pie 8 parts
mindmap 8 branches, 30 branches in all, at every level
argument 15 points
familytree 30 people
meter 6 meters, 5 bands per meter
rag 15 rows
clock 12 clocks

Emphasis

At most 2 elements in a document may take the emphasis role — nodes, items, levels, cells, positions, series and curves counted together. Emphasis says look here first, and when three things say it none of them is first. The third and every later one is refused at its role, with a message saying to keep the one or two the diagram is about. The strong edge role is not counted: it marks a path, which is several edges and reads as one line.

The objects

What the arrays above hold. Every one of them refuses a field it does not name, so a misspelt key is an error at the point it was written.

node object

Field Type Required What it is
id string yes Unique within the document.
centre boolean no Whether this node is the subject the rest are arranged around. One node per document may say so, and only a flow. For the diagram that starts in the middle rather than at the top: a thing with named relations on every side, where the relations are peers and there is no sequence between them. Ranked instead, the middle object becomes just another row.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of start, step, decision, terminal, emphasis, note, group, io, subroutine, store, person no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.
actor string no Who performs this step — free text, and orthogonal to role. role says what kind of step it is; this says whose it is, and the two are independent: a human step can be routine and an automated one can be the critical path. Drawn as the box’s lead, the name over what belongs to it, so the same words sit in the same place in every box and a reader can scan a column of them. Free text rather than an enum on purpose: an actor is told apart by its name, which is legible in greyscale and in any medium, so it costs none of the four non-colour channels the roles are told apart by. Only a flow, a tree or a cycle draws one, and a node that names an actor may not also write its own lead — the box has one lead and this is it.
note string no A short aside attached to this element. Only timeline draws one — it goes under the axis, beside the entry’s own mark. Every other kind accepts the field and has nowhere to put it, so it is not drawn; for text belonging to the whole diagram, use the top-level caption instead.
class string no Which of the document’s classes this box belongs to — an author-chosen grouping such as external system or owned by the payments team, drawn as that class’s faint fill and named in a key under the drawing. Must be the id of a declared class. Not on a note or a group, and not with status (both would mark the box). Only a flow, a tree or lanes.
status string — one of added, changed, removed no What a proposed change does to this box, as a diff would say it — for one drawing of the target state with the change marked on it, instead of a before and an after to compare by eye. Drawn as the labelled mark files uses (+ added, ~ changed, - removed) inside the box, never as a colour; a removed box is also dashed and its text struck through. Only a flow or a tree: a loop that changes is a different loop. An edge touching a removed box must be removed, and one touching an added box must be added.

edge object

Field Type Required What it is
from string yes The id of the source node — or, in a flow or a tree, of a group: an edge may name a container, for a relation that belongs to the whole of it rather than to any one box inside. It may not join a container to something already within it. A cycle draws no containers, so an edge in one names a node — or its hub, as a spoke.
to string yes The id of the target node — or, in a flow or a tree, of a group. The same id space as from. The same id as from draws a loop on the side of that box, across the reading direction, with its label outside it: two per box at most, and never on a group.
label string no A short label placed along the edge.
role string — one of flow, link, exchange, weak, owns, strong, aside, async no The semantic role, which the theme resolves to an appearance. Defaults to ‘flow’.
status string — one of added, changed, removed no What a proposed change does to this connection: the same marks as a node’s, written before the label (+, ~, -), with a key of the marks under the drawing. A removed edge is drawn in the aside treatment — dashed, no head — whatever its role. Only a flow, a tree or lanes.
polarity string — one of +, - no A causal link’s sign: more of the source means more (+) or less (-) of the target, written as the edge’s label (s/o under a theme that says so). Every flow or strong edge of the document has one, or none does. Only a flow.
delay boolean no The effect takes time: drawn as the double stroke across the shaft. Needs polarity. Only a flow.

loop object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
nodes array of string, at least 2 yes The loop’s variables in the order it runs: each joined to the next, and the last back to the first, by a signed edge in that direction.
type string — one of reinforcing, balancing no Optional, and checked: an even number of - links is reinforcing, an odd number balancing. Drawn as R or B, numbered in the order written.

lane-node object

Field Type Required What it is
id string yes Unique within the document.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of start, step, decision, terminal, emphasis, note, io, subroutine, store, person no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.
actor string yes Who performs this step, and so which lane it is drawn in. Required: every box in a swimlane diagram is in a lane. Drawn once, as the lane’s heading, and not repeated in the box — so text may again use a newline for its own lead and detail. Free text, matched exactly against lanes when that is given.
status string — one of added, changed, removed no What a proposed change does to this box, drawn as on a flow: the labelled mark inside the box, never a colour.
class string no Which of the document’s classes this box belongs to — an author-chosen grouping such as external system or owned by the payments team, drawn as that class’s faint fill and named in a key under the drawing. Must be the id of a declared class. Not on a note or a group, and not with status (both would mark the box). Only a flow, a tree or lanes.

hub object

Field Type Required What it is
id string yes Unique within the document, and in the same id space as the nodes, so an edge may name the hub — as a spoke, never as a step of the loop.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of start, step, decision, terminal, emphasis, note, group no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.

state object

Field Type Required What it is
id string yes Unique within the document, among the states and the groups.
text string no The state’s name. A newline makes it a lead and a detail, as on any box. Required on every state but a fork or join bar, which has no words.
role string — one of step, emphasis, terminal, fork, join no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’. fork and join make this state a bar: a fork has one transition in and two or more out, each into a different region of one composite; a join is the reverse. A bar has no text, and the transitions out of a fork or into a join carry no event or guard.

transition object

Field Type Required What it is
from string yes The state the machine leaves — or a group, for a transition that leaves the composite from whichever state inside it is current.
to string yes The state the machine enters — or a group, which is entered at its own initial. The same id as from draws a self-loop.
event string no What happens that moves the machine. Omit for a completion transition, taken as soon as the state’s work is done.
guard string no The condition that must hold for the event to move the machine. Written plainly; drawspec adds the brackets.
action string no What the machine does on the way. Written plainly; drawspec adds the slash. The label reads event [guard] / action, each part optional.
role string — one of flow, strong, weak no The semantic role, which the theme resolves to an appearance. Defaults to ‘flow’.

composite object

Field Type Required What it is
id string yes Unique within the document, among the states and the groups.
text string yes The composite state’s name, drawn at its frame’s corner.
members array of string, at least 1 no The states (or groups) inside this composite state. A composite lists its members or its regions, not both.
initial string no The member this composite is entered at, drawn as a dot inside the frame. Required when a transition, or the machine’s own initial, names the group. With regions, each region names its own instead.
regions array of state_region, at least 2 no Orthogonal regions: parts of this composite that are all current at once, drawn side by side (or stacked) and divided by dashed lines. Each region lists its own members and its own initial — unless every way into the composite is a fork with an arrow into that region, which says where it starts — and entering the composite enters every region there. A transition may not run between two regions of one composite. In place of members.

state_region object

Field Type Required What it is
members array of string, at least 1 yes The states (or groups) in this region. A state is in one region; each region is a machine of its own, running alongside the others.
initial string no The member this region starts in when its composite is entered, drawn as a dot inside the region. Required unless every way into the composite is a fork with an arrow into this region, which says where it starts instead.

participant object

Field Type Required What it is
id string yes Unique within the document, among the participants and the groups.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of step, emphasis, note, actor no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.

message object

Field Type Required What it is
id string no Optional, and only needed to name this message from a fragment. Unique among the messages.
from string yes The participant that sends it.
to string yes The participant that receives it. The same id as from is a message to itself, drawn as a hook on the right of its lifeline.
text string no What is said, written above the arrow. May carry inline spans. Omit for a bare arrow.
role string — one of flow, weak, strong, async no The semantic role, which the theme resolves to an appearance. Defaults to ‘flow’.
note string no A short aside about this message, drawn on its row in one column to the right of the last lifeline, so the notes read down as one margin.

fragment object

Field Type Required What it is
operator string — one of loop, alt, opt, par yes What the frame says about the messages inside it, written in its tab: loop repeats them, opt may happen, alt is one branch of several, par runs its branches at once.
from string yes The id of the first message inside the frame.
to string yes The id of the last message inside the frame — the same as from for a frame round one message. Not before from.
text string no The condition, beside the tab: what the loop runs over, when the option or the first branch happens. Written plainly; drawspec adds the brackets.
else array of branch no For alt and par only: where the frame is divided, each a dashed line above a message inside it, with that branch’s condition under it.

branch object

Field Type Required What it is
at string yes The id of the first message of this branch. The divider is drawn above it, so it is after the fragment’s first message and no later than its last.
text string no This branch’s condition. Written plainly; drawspec adds the brackets. Omit it for a par branch, which runs alongside the others and has none.

entity object

Field Type Required What it is
id string yes Unique among the entities.
text string yes The entity’s name, drawn bold over its fields. One line: may carry code and bold spans — a table name is usually code.
tag string no A short stereotype drawn over the name in guillemets — interface is drawn «interface». Free text, 16 characters at most.
role string — one of step, emphasis, note no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.
fields array of field no What the entity holds, one row each under its name: attributes, columns. A last field of ... stands for those not shown.
operations array of string no What a class can do — area() → float — drawn in a compartment of their own under the fields. Strings, not objects: an operation is read, never linked to.

field object

Field Type Required What it is
id string no Only needed for a relation to land on this row (from_field, to_field). Unique among the fields of the document.
text string yes The field’s name, one line. ... as the last field is a row standing for the fields not shown.
type string no Its type — uuid, float — drawn right-aligned in the monospace face.
key string — one of primary, foreign, unique no Whether it is a key, drawn as letters before the name — PK, FK, UQ: a word, never a colour.

relation object

Field Type Required What it is
from string yes The id of an entity. For inherits and realizes, the specific one — the subclass, the implementation.
to string yes The id of another entity — for inherits and realizes the general one, which gets the hollow triangle. Not the same as from.
from_field string no The id of one of the from entity’s fields: the line leaves that row, at the side facing the other entity, instead of the box. A foreign key drawn from its column.
to_field string no As from_field, a field of the to entity: the line arrives at its row.
from_end string — one of one, zero-or-one, many, zero-or-many, one-or-many no How many of the from entity there are per one of the other, drawn at the from end — crow’s feet or numbers, as the theme’s [entities] notation says. Not on inherits or realizes.
to_end string — one of one, zero-or-one, many, zero-or-many, one-or-many no As from_end, for the to end: how many of it per one of the other. Not on owns, whose to end is the whole, drawn as the diamond.
label string no A short label placed along the line.
role string — one of link, owns, weak, strong, inherits, realizes no What the relation is. link (the default) an association; owns composition — from is a part of to, diamond at to; weak a dependency; strong the relation that matters; inherits and realizes a subclass and an implementation, hollow triangle at to. An end with a cardinality draws it in place of the role’s head.

task object

Field Type Required What it is
id string yes Unique within the document.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
start number no Where the task starts on the axis, with end. A number in the axis’s unit (week 3, day 12, minute 45) — data, not a coordinate. Never a date.
end number no Where it ends, after start. With categories, 4 is where the fourth period begins.
at number no Instead of start and end: makes the task a milestone, drawn as a mark at this point with no length.
actor string no Who does it — free text, drawn as the row label’s lead, so the names line up in a column. A task with an actor may not put a newline in text.
done number no How much of the task is complete, 0 to 100: drawn as a solid band inside the bar from its start, MS Project’s progress line. Not on a milestone.
role string — one of step, strong, emphasis, note no step (the default bar), strong (on the critical path: drawn heavier, the word its dependencies take), emphasis (the task the diagram is about) or note (outside the plan, drawn lighter).

dependency object

Field Type Required What it is
from string yes The id of the task that has to finish first.
to string yes The id of the task that waits for it, which may not start before from ends. Drawn from the end of one bar into the start of the other.
role string — one of flow, strong, weak no flow (the default), strong (the critical path) or weak (a soft dependency, dashed).

mark object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
at number yes Where on the axis: a line is drawn across every row there.

axis-gantt object

Field Type Required What it is
label string yes Required, and the unit’s name: Week, Day, Minutes after 02:00.
unit string no What the numbers are in, written after the label.
min number no Where the plan starts. Omit to take it from the tasks.
max number no Where the plan ends. Omit to take it from the tasks.
categories array of string, at least 1 no Names for the periods, in order, instead of numbers — months, sprints, quarters. The first period runs from 1 to 2, the second from 2 to 3, so a task over the first three is start 1, end 4. Sets the range itself, so not with min or max.

board-column object

Field Type Required What it is
id string yes Unique among the columns; what a card’s column names.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
limit integer, greater than 0 no A work-in-progress limit. drawspec counts the column’s cards (a note card is not work, so it is not counted) and writes n / limit in the heading; over the limit the heading takes emphasis. Never write the count yourself.
role string — one of step, emphasis no step (the default) or emphasis (the column the board is about), drawn as the weight of the rule under the heading.

slice object

Field Type Required What it is
id string yes Unique among the rows; what a card’s row and the board’s cut name.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.

card object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
column string yes The id of the column it is in. Its kind is its column.
row string no The id of the row (slice) it is in. Required when the board has rows, refused when it has none.
role string — one of step, emphasis, note no step (the default), emphasis (blocked, at risk, the one that matters) or note (a placeholder or a summary such as + 6 more, drawn lighter and not counted against a limit).
actor string no Who holds it — free text, drawn as the card’s lead, as in a flow box. A card with an actor may not put a newline in text.
note string no A short aside hung under the card, smaller: blocked on a decision.

venn-set object

Field Type Required What it is
id string yes Unique among the sets; what a region’s in names.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of step, emphasis no step (the default) or emphasis (the set the diagram is about), drawn as a heavier outline.

region object

Field Type Required What it is
in array of string, at least 1 yes The ids of exactly the sets this region is in, and no others: ["gdpr"] is what only that set holds, ["gdpr", "ens"] what the two share. drawspec knows where that region is.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of step, emphasis no step (the default) or emphasis (the region the diagram is about): its words bold and the region filled with the theme’s first mark fill.

journey-row object

Field Type Required What it is
id string yes Unique among the rows; what a stage’s details name in row.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.

journey-stage object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
feeling string yes One of the journey’s feelings, by name: the level this stage’s point is drawn at. A name, never a score.
role string — one of step, emphasis no step (the default) or emphasis (the stage the map is about, usually the trough): its column framed, its point drawn larger and solid.
details array of detail no What this stage holds in each detail row, a {row, text} per row it fills. A row it does not name is drawn as an empty cell.

detail object

Field Type Required What it is
row string yes The id of one of the journey’s rows, at most once per stage.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.

treemap-part object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
amount number, greater than 0 yes How much of the total this part is, in the treemap’s unit: its area is in proportion. A number you already know, more than 0.
group string no The id of one of the treemap’s groups: the part is laid out with the group’s other parts inside its captioned frame. Omit it to sit beside the groups.
role string — one of step, emphasis, note no step (the default), emphasis (the part the diagram is about — not automatically the largest: a heavier outline, its words bold) or note (the remainder, Everything else: a light dashed outline, laid out last).

sankey-node object

Field Type Required What it is
id string yes Unique among the nodes; what a flow’s from and to name.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of step, emphasis, note no step (the default), emphasis (the node the diagram is about: its bar outlined heavier, its words bold) or note (the remainder — Lost, Reserved, idle — drawn lighter, with the bands that reach it).

sankey-flow object

Field Type Required What it is
from string yes The id of the node the amount leaves.
to string yes The id of the node the amount reaches.
amount number, greater than 0 yes How much flows, in the sankey’s unit: the band’s thickness is in proportion. A number you already know, more than 0.
role string — one of flow, strong no flow (the default band) or strong (the path the diagram is about, drawn darker).

axis-numberline object

Field Type Required What it is
min number yes Where the scale starts, at the left arrowhead’s side.
max number yes Where the scale ends: more than min.
step number, greater than 0 no The distance between two ticks, each labelled with its number. Omit it for a step a reader can count in, chosen from the range.
label string no What the numbers measure, centred under them: pH, Temperature.
unit string no What the numbers are in, written after the label: °C, cm.
ends array of string, at least 2 no Two words for the low and the high end — past and future, fully remote and fully on site — written under the arrowheads, for a scale that is named rather than measured. No numbers are drawn: only the order and the gaps count, so not with step or unit.

numberline-point object

Field Type Required What it is
at number yes Where the dot sits on the axis: a number between min and max.
text string no The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
open boolean no Whether the dot is hollow: the value itself is excluded — x ≠ 3, a hole. Defaults to false, a filled dot.
role string — one of step, emphasis, note no step (the default), emphasis (the point the line is about: a larger dot, its words bold) or note (context: a smaller dot).

numberline-range object

Field Type Required What it is
from number no Where the range starts. Omit it for a range that runs on below min, drawn as an arrow off the left end.
to number no Where the range ends: more than from. Omit it for a range that runs on above max, drawn as an arrow off the right end.
from_open boolean no Whether from is excluded — x > 1 rather than x ≥ 1. Defaults to false. The theme’s [numberline] ends draws it as a hollow dot or a parenthesis.
to_open boolean no Whether to is excluded — x < 4 rather than x ≤ 4. Defaults to false.
text string no The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of step, emphasis, note no step (the default, a heavy line), emphasis (the range the line is about — the solution set: a heavier bar, its words bold) or note (context: dashed).

barmodel-bar object

Field Type Required What it is
id string no What a brace’s over names, for a brace over the whole bar. Unique among the bars and the parts.
text string no The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
parts array of barmodel-part, at least 1 yes The bar’s parts, left to right, each as long as its value or its units say — in one scale for every bar.

barmodel-part object

Field Type Required What it is
id string no What a brace’s over names. Unique among the bars and the parts.
amount number, greater than 0 no How much the part is, more than 0: its length is in proportion, and its words default to the number. Give it even for the unknown — the ? is its text.
units integer, greater than 0 no How many equal boxes the part is, each one unit long: groups to multiply, the shares of a ratio, the fifths of a fraction. Not with amount, and not in a document whose parts have amounts.
text string no The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of step, emphasis, note no step (the default), emphasis (the part the problem asks about: bold words, filled) or note (a part that is not there — the difference a shorter bar lacks: dashed).

barmodel-brace object

Field Type Required What it is
over array of string, at least 1 yes What the brace spans: the ids of side-by-side parts of one bar, drawn over it (under it, for the last of several bars), or of whole bars — one bar the same way, several consecutive bars with an upright brace at their right.
amount number, greater than 0 no What the stretch adds up to. Checked: the parts’ amounts must sum to it, and with units every brace must make one unit worth the same. Written unless text is given.
text string no The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.

waterfall-axis object

Field Type Required What it is
label string yes What the numbers are, with their unit — Borrowing, £ billion. Set beside the vertical axis; required, as on every chart.

waterfall-bar object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
total number no A total: the bar stands on zero and runs to it. The first bar is one and so is the last; one in between is a subtotal. Every total after the first is checked: it must be the running sum. Not with amount.
amount number no A signed step, not 0: the bar floats from the running sum to the running sum plus this, and is written +6.1 or −9.4. Not with total.
role string — one of step, emphasis no step (the default) or emphasis (the bar the chart is about: a heavier outline, its number bold).

pie-part object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
amount number, greater than 0 yes How much of the total this part is, more than 0, in the pie’s unit: a count, a sum, or with unit: "%" a percentage. Its angle is its share of the sum of the amounts, computed — never written.
role string — one of step, emphasis, note no step (the default), emphasis (the part the chart is about: a heavier outline, its words bold) or note (the remainder, Everything else: unfilled and dashed, drawn last). At most one note.

argument-point object

Field Type Required What it is
id string yes Unique within the document, and not claim: what on and with name.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
on string yes The box this point bears on: claim, or another point’s id. The points hang below it, in the order written.
stance string — one of for, against yes for (a reason, drawn plain, tagged because) or against (an objection, hatched, tagged but) the box it is on. A rebuttal is an against on an against.
with array of string, at least 1 no Co-premises: the ids of points with the same on and stance that support it only together. Written once, on any member; the group is every point joined this way, at most 4, drawn side by side under one bracket with one connector.
role string — one of step, emphasis, note no step (the default), emphasis (the decisive point: heavy outline and connector, bold words) or note (evidence or a source rather than a reason: the note type, unboxed, on a dashed connector).

familytree-person object

Field Type Required What it is
id string yes Unique within the document: what couples name.
sex string — one of male, female, unknown yes The symbol: a square (male), a circle (female) or a diamond (unknown), as the standard nomenclature draws them. With gender, the symbol shows the gender instead and this is noted under it (AMAB, AFAB) when the two differ.
gender string — one of man, woman, nonbinary no Gender identity, per the 2022 revision of the standard: the symbol becomes a square (man), a circle (woman) or a diamond (nonbinary), and sex is the sex assigned at birth, written under it when it differs. Leave it out and the symbol follows sex.
text string no The name, or an age or a test result, under the symbol and its number. A newline makes it a lead and a detail, as anywhere: a name over the years.
status string — one of affected, carrier, unaffected no The one trait the tree tracks: affected (the symbol filled), carrier (the theme’s carrier mark: a dot in the middle, or the left half filled) or unaffected (the default: empty). Told apart without colour; a key under the drawing names the ones used.
deceased boolean no A diagonal stroke through the symbol. An age or year goes in text.
proband boolean no The affected person through whom the family came to attention: an arrow at the lower left with a P. One per tree.
consultand boolean no The person asking for advice or testing: the arrow without the P. May be the proband too.
adopted boolean no Adopted into the couple whose children list them: brackets round the symbol and a dashed line down from the sibship line. A child is listed once, in the couple that raised them.
pregnancy string — one of ongoing, loss no ongoing: a P in the symbol (the weeks go in text); loss: a small triangle in place of the symbol, shaded when affected. Either is a child only: no partners.
role string — one of step, emphasis no step (the default) or emphasis: the person the figure is about when there is no proband — a heavier symbol and a bold name.

familytree-couple object

Field Type Required What it is
between array of string, at least 2 yes The two partners’ ids, in either order: drawspec puts them side by side, joined by the partner line. A person’s couples are their partners in the order written — marriage order — at most 6.
children array of string no Their children’s ids, in birth order: left to right under the sibship line. Leave it out for a couple with none.
twins array of familytree-twins no Children of one birth, each set written next to each other in children.
separated boolean no The relationship has ended: two short strokes across the partner line.
consanguineous boolean no The partners are related by blood: a double partner line.

meter-meter object

Field Type Required What it is
text string yes The meter’s name. A second line after a newline is its caption, drawn plain under the name: what the reading is of — This year's milestones only.
amount number yes The reading, on the scale from min to max. Written with its unit in the readout; never as a percentage the author worked out.
max number yes The end of the scale: a thermometer’s goal, a progress bar’s whole, a dial’s right-hand end.
min number no Where the scale starts, on a dial only (0 by default): a needle reads a position, so it may start anywhere. A bar’s length is its amount, so a bar, a bullet and a thermometer start at 0.
unit string no What the numbers are in: %, a currency sign (£, $, €, ¥, written before the number) or a word (tasks, after it).
target number no A mark on the scale — the plan, a stage of an appeal — drawn across the track and written in the readout. Inside the scale.
bands array of meter-band, at least 2 no Named stretches of the scale, rising: each runs from the end of the one before (or min) to its own to, and the last ends at max. Required on a bullet, optional on a dial, refused on the others. Drawn in tones of the page’s ink with their words on them, so a band is never told by colour alone.
role string — one of step, emphasis no step (the default) or emphasis (the meter the panel is about: its name and reading bold).

clock-face object

Field Type Required What it is
time string no The time the hands show, H:MM or HH:MM from 0:00 to 23:59 — 15:40 for twenty to four in the afternoon. No seconds, no date. Leave it out for a face with no hands, to draw them on.
text string no A name or a prompt under the face: Home time, Draw half past seven.
since string no An earlier time, H:MM, up to 12 hours before time: the face shades what has passed since it, and the readout says how long.

rag-row object

Field Type Required What it is
text string yes The workstream or risk. A second line after a newline is a caption under it, at the label size: an owner, a reference.
rag string — one of red, amber, green yes The rating: red, amber or green. Drawn as the theme’s word and shape for it (and its colour, when the theme has one), so it is never told by colour alone.
trend string — one of better, same, worse no The direction of travel since the last report: better, same or worse. Drawn as an arrow (up, across, down) with the theme’s word beside it.
note string no Why: a sentence or two of commentary, wrapped in the last column. **bold** for a decision asked for.

meter-band object

Field Type Required What it is
text string yes The band’s name, written on it: Good, Strained, or Green when that is the word the reader is taught. One or two short words.
to number yes Where the band ends; it starts where the band before ends.

familytree-twins object

Field Type Required What it is
of array of string, at least 2 yes Two or three of the couple’s children, next to each other in children: drawn from one point on the sibship line.
zygosity string — one of monozygotic, dizygotic, unknown yes monozygotic (identical: a bar joins their lines), dizygotic (fraternal) or unknown (a ? between them).

mindmap-branch object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of step, emphasis, note no step (the default), emphasis (the branch the map is about: bold, its line heavy all the way from the centre; at most two) or note (context, not content: faint, and so is everything under it).
branches array of mindmap-branch, at least 1 no The branches off this one, drawn top to bottom in the order written. At most three levels below the centre: a branch, a twig, a leaf.

treemap-group object

Field Type Required What it is
id string yes Unique among the groups; what a part’s group names.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.

effect object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.

category object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
causes array of cause, at least 1 yes What was investigated under this category, in reading order from the category’s name inwards to the spine. Leaves: a cause has no causes.

cause object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of step, emphasis, note no step (the default), emphasis (the confirmed root cause: its bone is drawn heavy up to the spine) or note (investigated and ruled out, its tick drawn light and dashed).

group object

Field Type Required What it is
id string yes Unique within the document.
text string no The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
members array of string, at least 1 yes The ids of the nodes this group contains, in the order they are meant to read — the members of a container are an ordered set.

band object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
members array of string, at least 1 yes The ids of the nodes this band accompanies. Unlike a group’s, they are a set rather than a container: a band names something that runs alongside those boxes, and the same box may be under any number of bands.

class object

Field Type Required What it is
id string yes What a node’s class names. Unique among the classes.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.

phase object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
members array of string, at least 1 yes The ids of the steps in this phase, in any order and in any lane. Every step is in one phase, so a step left out or listed twice is refused.

item object

Field Type Required What it is
id string no Optional; generated from position when absent.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of start, step, decision, terminal, emphasis, note, group no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.
note string no A short aside attached to this element. Only timeline draws one — it goes under the axis, beside the entry’s own mark. Every other kind accepts the field and has nowhere to put it, so it is not drawn; for text belonging to the whole diagram, use the top-level caption instead.
at number no For timeline: when this happened, so the gaps mean something. Give it to every entry or to none.

level object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of start, step, decision, terminal, emphasis, note, group no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.
note string no A short aside attached to this element. Only timeline draws one — it goes under the axis, beside the entry’s own mark. Every other kind accepts the field and has nowhere to put it, so it is not drawn; for text belonging to the whole diagram, use the top-level caption instead.

ring object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of start, step, decision, terminal, emphasis, note, group no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.

cell object

Field Type Required What it is
id string no Optional, and only needed to join this cell to another: an edge names the two cells it runs between. Unique within the document.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
column integer yes Which column this cell starts in, counting from zero.
row integer yes Which row it starts in, from zero.
across integer no How many columns it covers. Default 1.
down integer no How many rows it covers. Default 1.
group string no Which group this cell belongs to. Cells sharing a group are filled alike; the theme decides how. Naming the fill itself is not an author’s decision.
role string — one of start, step, decision, terminal, emphasis, note, group no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.

waypoint object

Field Type Required What it is
id string no Optional, and only needed to measure from this point: a span names the two waypoints it runs between. Unique within the document.
text string no What to call this point. Omit for a point that only shapes the curve.
across number yes Where this sits on the horizontal axis. Data, not a coordinate.
up number yes Where this sits on the vertical axis. Data, not a coordinate.

curve object

Field Type Required What it is
name string no Drawn where the curve ends. Omit it when there is only one curve and the axes already say what it is.
waypoints array of waypoint, at least 2 yes The points the curve passes through, in order. Two is a line.
role string — one of start, step, decision, terminal, emphasis, note, group no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.

entry object

Field Type Required What it is
path string yes Where this sits, from the top of the tree: src/app/main.py. The folders it passes through are drawn without being listed. A trailing / makes it a folder — needed only for one with nothing listed inside. A last segment of ... is a row standing for entries not listed.
note string no A short comment drawn after the name, in the smaller label type.
link string no Makes this entry a symbolic link, drawn with an arrow to this target. Written, never followed: the target need not be in the tree.
status string — one of added, changed, removed no What a change did to this entry, as a diff would say it. Drawn as a labelled mark after the name — never as a colour alone.

position object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
across number yes Where this sits on the horizontal axis. Data, not a coordinate.
up number yes Where this sits on the vertical axis. Data, not a coordinate.
role string — one of start, step, decision, terminal, emphasis, note, group no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.

stage object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
role string — one of start, step, decision, terminal, emphasis, note, group no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.
gate string no What stands between this stage and the next — the threshold a thing has to pass to get from one to the other, which is what makes a stage-gate model one. Drawn on the divider, which breaks to let it through. The last stage has no next stage, so it may not carry one.
note string no A short aside attached to this element. Only timeline draws one — it goes under the axis, beside the entry’s own mark. Every other kind accepts the field and has nowhere to put it, so it is not drawn; for text belonging to the whole diagram, use the top-level caption instead.
amount number, greater than 0 no On a funnel stage: how many reached it. Written under the name, with the share kept from the stage before; the taper stays the drawing’s own, not to scale. Every stage or none, never more than the stage before.

span object

Field Type Required What it is
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.
from string yes The id of the entry the interval starts at.
to string yes The id of the entry it ends at. Must come after from.

key object

Field Type Required What it is
group string yes Which group this names. Some cell must belong to it.
text string yes The words themselves. May carry inline spans — code for the monospace role and bold for emphasis — because those are semantic, not typographic. A newline says this label is a lead and a detail rather than one sentence; the theme’s [box] lead decides what the first paragraph looks like. Prefer it to punctuating the two apart inside one line.

axis object

Field Type Required What it is
label string yes Required: an unlabelled axis cannot be read.
unit string no What the numbers are in, written after the label.
min number no Where the axis starts. Omit to take it from the data.
max number no Where the axis ends. Omit to take it from the data.
categories array of string no Names for the positions 1, 2, 3 … along this axis, instead of numbers. What a bar chart’s horizontal axis usually is: the quarters, the service models, the teams. On a chart’s vertical axis they make horizontal bars: every series a bar, each point [amount, position], the first category the top row, names on the left.

axes object

Field Type Required What it is
horizontal axis object yes The axis across.
vertical axis object yes The axis up.

axis-quadrant object

Field Type Required What it is
label string yes Required: an unlabelled axis cannot be read.
unit string no What the scores are in, written after the label.
min number no Where the axis starts. Omit to take it from the positions.
max number no Where the axis ends. Omit to take it from the positions.
ends array of string, at least 2 no Two words for the low and the high end — Low and High, Rarely and Often — written at the two ends of the axis, as on a numberline.

axes-quadrant object

Field Type Required What it is
horizontal axis-quadrant object yes The judgement across.
vertical axis-quadrant object yes The judgement up.

axis-continuous object

Field Type Required What it is
label string yes Required: an unlabelled axis cannot be read.
unit string no What the numbers are in, written after the label.
min number no Where the axis starts. Omit to take it from the data.
max number no Where the axis ends. Omit to take it from the data.

axes-continuous object

Field Type Required What it is
horizontal axis-continuous object yes The axis across, read as a measurement — unlike quadrant’s.
vertical axis-continuous object yes The axis up, read as a measurement — unlike quadrant’s.

series object

Field Type Required What it is
name string yes What to call this series, in the legend and at its end.
data array of [x, y] pairs, at least 1 yes The values to plot, as [x, y] pairs. Data, not coordinates.
role string — one of start, step, decision, terminal, emphasis, note, group no The semantic role, which the theme resolves to an appearance. Defaults to ‘step’.
mark string — one of line, bar, area no How this series is drawn: a line, bars, or a filled area. Default ‘line’.
stack string no Series sharing a stack name are piled on each other rather than drawn side by side. Bars and areas only.

What may not be written

Every object above refuses a field it does not name. When the field is one of these, the refusal says why rather than just listing the legal keys — and it carries the JSON pointer of the place it was written. This is the list that makes the failures in docs/brief.md unexpressible rather than merely discouraged: a document cannot say where a box goes, so a box cannot go in the wrong place.

The Where column matters. Most of these names are legal nowhere at all. A few are legal at the document root and refused on everything inside it — height, width size the canvas, which is a budget for the whole drawing, and are exactly the wrong thing to say about one box in it.

Field Where it is refused Why not
anchor Everywhere edge geometry comes from the edge’s semantic role
arrow_head Everywhere say role: “link”, not arrow_head: “none” — head geometry is the theme’s
canvas Everywhere derived from width and the content
color Everywhere appearance is a property of the role, not of the element
cx Everywhere coordinates are the tool’s output, never its input
cy Everywhere coordinates are the tool’s output, never its input
d Everywhere coordinates are the tool’s output, never its input
dash Everywhere line treatment comes from the edge’s semantic role
dx Everywhere coordinates are the tool’s output, never its input
dy Everywhere coordinates are the tool’s output, never its input
fill Everywhere appearance is a property of the role, not of the element
font_family Everywhere type is selected by semantic role from the theme’s scale
font_size Everywhere type is selected by semantic role from the theme’s scale
font_weight Everywhere type is selected by semantic role from the theme’s scale
height On any object — legal at the document root box geometry is derived from measured text plus theme padding
layer Everywhere overlap is resolved by the layout, not declared
order Everywhere overlap is resolved by the layout, not declared
points Everywhere coordinates are the tool’s output, never its input
port Everywhere edge geometry comes from the edge’s semantic role
stroke Everywhere appearance is a property of the role, not of the element
stroke_width Everywhere appearance is a property of the role, not of the element
value Everywhere a cell is filled by the scale step its group names, not by a number — bucket the values and name the buckets; the number can stay in the text
viewBox Everywhere derived from width and the content
width On any object — legal at the document root box geometry is derived from measured text plus theme padding
x Everywhere coordinates are the tool’s output, never its input
y Everywhere coordinates are the tool’s output, never its input
z Everywhere overlap is resolved by the layout, not declared