FigDown

Figures as text in Markdown — one source, two readers.

A missing edge still looks fine. Text doesn’t. An invented node and a dropped edge are both invisible in a picture that looks fine. FigDown keeps figures as text whose source states the meaning — participants, containment, field widths, table structure — so the next reader can check it, not just look at it.

FigDown is an open standard for describing figures as plain text inside Markdown, so that one source serves two readers who need completely different things from it:

One source, two readers: a .fd file feeds the FigDown renderer, which produces an SVG for a human reader; the same .fd is read directly for meaning by an AI agent.

source: figures/one-source-two-readers.fdthis figure is FigDown.

The claim, shown rather than described

Below is one FigDown document in both of its forms. The picture on the left is what a human reads; the text on the right is what an agent reads. They are the same content, the picture was rendered from that text by FigDown itself, and the text is examples/dns.fd in full — 30 lines, nothing elided.

DNS message header from RFC 1035: six 16-bit words with a bit ruler numbered 0 to 15, the flags word split into QR, Opcode, AA, TC, RD, RA, Z and RCODE at their real bit widths, and a variable-length section below.
# FigDown — figures as text. Spec: https://github.com/FigDown/figdown

figdown 0.1 bitfield

# DNS Message Header — RFC 1035 §4.1.1
# Each row is 16 bits, MSB-0 numbering (bit 0 at left).

bitfield dns "DNS Message Header (RFC 1035)" word=16 numbering=msb0

# Row 1: Transaction ID
field "ID" 16 description="Identifier assigned by the program that generates the query; copied into the reply"

# Row 2: Flags (QR + Opcode + AA + TC + RD + RA + Z + RCODE = 16 bits)
field QR:1,Opcode:4,AA:1,TC:1,RD:1,RA:1,Z:3,RCODE:4

# Row 3: Question Count
field "QDCOUNT" 16 description="Number of entries in the question section"

# Row 4: Answer Record Count
field "ANCOUNT" 16 description="Number of resource records in the answer section"

# Row 5: Authority Record Count
field "NSCOUNT" 16 description="Number of name server resource records in the authority section"

# Row 6: Additional Record Count
field "ARCOUNT" 16 description="Number of resource records in the additional records section"

# Variable-length sections (one representative row each)
break
field "Question / Answer / Authority / Additional sections" * description="Variable-length sections follow the header; see RFC 1035 §4.1.2–4.1.4"

source: examples/dns.fd — a bit ruler numbering 0–15, and a flags word split into eight sub-byte fields at their real widths. No Markdown-native diagram tool draws that. An agent reads the same facts off the text: RCODE is the low four bits of the second 16-bit word, and the sections after the header have a width the document deliberately declines to give.

One document, several coordinated forms

A .fd is not one picture per file. One document can yield several forms that have to keep agreeing with each other — and a figure is only evidence at a size where its text can be read, so there is one here, at full width.

VXLAN encapsulation: the Ethernet frame before encapsulation and the VXLAN-encapsulated frame after it, an overhead table, and a legend derived from the class declarations.

source: examples/vxlan-encap.fd — the same frame before and after encapsulation in one document, plus the encapsulation overhead. The legend is derived from the class declarations; nobody drew it.

examples/pvlan-flows.fd goes further and needs its own page: one document yielding a topology, a derived legend and two rule tables, because the prohibitions that define a private VLAN cannot be drawn as arrows and have to be written down. It is 1243×832 with four sub-figures, so it is shown full size in the example gallery rather than shrunk to fit here.


Where to go

Releases and the archive

Every released version keeps one git tag and one archived engine page that is never rewritten, so a figure written today can always be re-rendered exactly as it was. Current release v0.5.1: archive/0.5/figdown.html. Earlier archived pages (0.10.4) and every release's tag are indexed in spec/migrations.md. The editor above tracks the current development state and is not an archive.