Specification · .dgm 1.0
A diagram format meant to be written, not drawn
Every format we import was designed for a canvas with a mouse on it. Each fails a writer with no eyes the same way: it asks for geometry. This one asks for meaning.
Why it exists
draw.io, Excalidraw and tldraw are scene graphs: every element carries an absolute
x and y,
so a model has to invent coordinates whose consequences it cannot see. Visio adds an OPC
zip and master indirection on top. Mermaid is the closest thing to writable and still
couples the drawing to a layout direction, has no way to say what a box is, and
resolves ambiguity by position.
In .dgm the author declares meaning and the
renderer owns every pixel. There are no coordinates in the format at all.
A whole file
dgm: 1.0
diagram: architecture
title: Content site in production
direction: LR
zones:
content: Content
nodes:
reader: { label: Reader, role: actor, note: Browser }
cdn: { label: Cloudflare, note: "Pages · cache" }
origin: { label: Astro Origin, note: SSR + MDX, focus: true }
mdx: { label: MDX Bundle, role: store, in: content }
cms: { label: Content CMS, role: store, in: content }
flow:
- reader -> cdn: HTTPS
- cdn -> origin: SSR
- origin ~> mdx: read mdx
- origin ~> cms: query
- cdn ..> reader: resp
steps: [cdn, origin]
Keys
Node fields
Drawing fields
Four kinds are engineering drawings rather than figures — network,
electrical, circuit and
floorplan — and carry facts a figure does not. A drawing is
80% annotation: the model, the address, the rating, the cable, each in a fixed place. These fields
hold them. They are ignored on every other kind.
Links take three more, written as a mapping since the arrow shorthand cannot carry them:
{ from: sw, to: fw, directed: false, ports: [gi1/0/1, lan1], label: 1G, medium: fibre, pair: 2 }.
ports is the interface at each end, in order, with "" where an end has none;
medium is wired, fibre, wireless or vpn and is drawn as a stroke;
pair says how many parallel links this stands for. Write network links with
-- or directed: false — a LAN carries traffic both ways.
Zones take subtitle (a subnet, a VLAN, a board rating — drawn after the name) and
style: zone | enclosure. On a network the zones are the tiers, top to bottom
in the order declared; on an electrical drawing a zone styled enclosure is drawn as the
board's boundary. A door on a floor plan is an edge between two rooms, placed where their rectangles touch; a junction on a
schematic is derived wherever conductors meet. Neither is written by hand, so neither can be wrong.
Arrows
A relationship carries a kind, not just a line style, so "queries" and "returns" survive
a round trip instead of collapsing to "arrow". Any connection may take
: label.
- a -> b
- Primary flow. Solid, in the brand colour.
- a ~> b
- A call or a query — a request to something that answers.
- a ..> b
- A return or an async hand-off. Dashed, and it does not advance the reading order.
- a -- b
- A plain association with no direction.
A connection may also be written as a mapping —
{ from: a, to: b, kind: call, label: query } —
which generators sometimes prefer. JSON is accepted wherever YAML is: JSON is what models
emit most reliably, YAML is what people diff most comfortably, and both parse to the same
document.
Versioning
The current version is 1.0,
declared as dgm: 1.0
on the first line of every file we write.
- Minor versions are additive. A reader on 1.0 must accept a 1.1 file and ignore what it does not recognise. Otherwise every field we ever add breaks every deployment that has not upgraded.
- A major version is a promise being broken and is refused rather than guessed at, by name, in the error. We would keep reading the old major rather than orphan documents people have committed to a repository.
- A file with no
dgm:key is 1.0 and stays valid — the first version shipped before the key did.
Errors are repair instructions
The writer is usually a model fixing its own output, so a rejection names the thing that is wrong rather than the line number it is on: an edge pointing at an undeclared node is refused by that node's id, and a connection with no arrow is answered with the list of arrows. Nodes are a map keyed by id, so a duplicate id cannot be expressed at all.
Round trip
Every other artifact we produce is terminal: you get a picture and cannot get the diagram
back, which is why a conversion carries a fidelity ledger at all. What we write as
.dgm re-imports to the same drawing, and the
writer is idempotent, so the file in a repository stops changing after one pass. Convert a
.vsdx once, keep the
.dgm, and never open Visio again.