The language

Six forms, and that is the whole syntax. Every page after this one adds a layout — a new way to arrange children. None of them adds a rule.

One line draws

draft -> review -> publish
draft review publish

Nothing was declared there. A link to a name nobody declared creates a box for it, labelled with the name.

A chain marks every hop, so that line is exactly draft -> review and review -> publish.

Declare a node when you have more to say about it

|oval#visitor| "Visitor"
|box#api| "API"
|cyl#db| "Postgres"

visitor -> api -> db
Visitor API Postgres

The bars carry the identity — a type, and an id after #. The quoted string is the label.

Only the bars are required, and both halves inside them are optional:

  • |box#api| is a box named api with no label — a blank card, not a card reading “api”.
  • |#api| is that same box. A node with no type is a |box|.
  • |oval| is an oval nothing can link to, because an id is the one thing you reference.

Style is a block on the node

|box#edge| "Edge"
|box#core| "Core" { fill: --rose-wash; stroke: --rose-deep; radius: 14; }

edge -> core
Edge Core

A { } after the label is that node’s style: key: value; declarations, and the vocabulary is the same everywhere in the language.

Children go in brackets

{ gap: 76; }

|box#web| "Web" { fill: --rose-wash; stroke: --rose-deep; color: --rose-ink; }
|box#api| "API" { fill: --purple-wash; stroke: --purple-deep; color: --purple-ink; }
|group#store| "Store" { direction: column; gap: 26; padding: 22; } [
  |box#cache| "Cache" { fill: --purple-wash; stroke: --purple-deep; color: --purple-ink; }
  |cyl#db| "Postgres" { fill: --purple-wash; stroke: --purple-deep; color: --purple-ink; }
]

web -> api
api -> store.cache
api --> store.db
Web API Cache Postgres Store

A [ ] holds content — children, in the order written.

A named container gives its children a path, which is how store.cache and store.db reach them from outside. There is no search: cache alone at the root would make a new box rather than find that one.

Four nodes here carry the same three declarations. That is the itch the next section scratches.

The stylesheet on top

Everything so far styled one node at a time. A { } block standing before any drawn statement is the stylesheet: it draws nothing, and it says what whole kinds of thing look like.

{
  gap: 80;
  |box| { radius: 4; }
  |-| { stroke: --gray-deep; font-size: 12; }
  .hot { fill: --rose-wash; stroke: --rose-deep; }
  |svc::box| { fill: --purple-wash; stroke: --purple-deep; }
}

|svc#web| "Web"
|svc#api| "API" .hot

web -> api "HTTPS"
Web API HTTPS

Four kinds of entry, each reaching a different way:

  • |box| { } is a rule — every node of that type. |-| is the link type, so that line styles every link on the page.
  • .hot { } is a class, worn after the label: |svc#api| "API" .hot.
  • |svc::box| { } is a define — a new type carrying its own defaults over a base one.
  • gap: 80 is a bare declaration, and belongs to the root. The file is the body of an implicit root container, so its children are your top-level nodes.

An #id { } rule reaches exactly one node. When several of these touch the same property, the more specific one wins; the style page walks the ladder.

The six forms

Everything above is built from these, and there are no others:

FormMeans
|type#id|Identity — a type and an optional id, always in bars.
"…"The label. Each type decides where it goes: centred in a box, the caption of a group, the title of a chart.
{ … }Style — declarations. On a node it is that node’s; before any statement it is the root’s stylesheet.
[ … ]Content — children, in the order written.
.nameA class, defined once and worn after the label.
a -> bA link — two ids and an operator. The operator is the look.

A drawn node is |type#id| "label" .class { style } [ children ], and a link is the same tail on a different head: a -> b "label" .class { style }. A name goes bare only when it is being referenced, and the one thing you reference is an id — which is why types and classes always carry their sigil.

Where each family starts

A layout: on any container — the root, or any node — picks the family:

WriteGetTour
layout: flow (default) · gridboxes in a row, a column or a gridDiagrams
layout: tree · |mindmap|a hierarchy from nesting aloneTrees & mindmaps
|table| · |entity|ruled grids and ER cardsTables & entities
layout: sequenceparticipants, lifelines and messages on a time axisSequences
layout: chart · piebars, lines, areas, dots, slicesCharts
layout: drawinga dimensioned engineering sheetDrawings
layout: floorplanwalls, openings and fixturesFloor plans
layout: schematicparts, pins and routed wiresSchematics

The nodes, links, cascade and colours are identical in every one. A layout only decides where its children go, and what its links mean.