DOT examples

Every example on this page is complete — paste any of them into Import as-is. Below each one is what it actually renders: the images are produced by Drawbridge itself, headless, from exactly the code shown (scripts/render-doc-examples.mjs) — not illustrations, output. A test (app/src/manual/api-reference.test.ts) runs every example through the real parser and checks its render is present, so an example that stops working fails the build before it can mislead you.

Three lines

digraph { internet -> firewall -> switch }

Rendered by Drawbridge v0.61.4 from the code above (light theme)Rendered by Drawbridge v0.61.4 from the code above (dark theme)

No attributes at all: the names themselves pick the icons, and the arrows make three tiers.

A small office

digraph office {
  inet [kind=internet, label="Internet"]
  fw1  [kind=firewall, label="FW-EDGE",
        mgmtIp="192.0.2.1"]
  core [kind="l3-switch", label="CORE-1"]
  acc1 [kind=switch, label="ACC-1"]
  acc2 [kind=switch, label="ACC-2"]
  ap1  [kind="wifi-ap", label="AP-LOBBY"]
  srv1 [kind=server, label="SRV-FILES"]
  db1  [kind=database, label="DB-PROD"]
  inet -> fw1
  fw1:port1 -> core:ge1 [speed="10G"]
  core -> {acc1 acc2} [speed="1G"]
  acc1 -> ap1
  acc2 -> {srv1 db1}
}

Rendered by Drawbridge v0.61.4 from the code above (light theme)Rendered by Drawbridge v0.61.4 from the code above (dark theme)

What to notice: quoted values wherever a hyphen appears ("l3-switch", "wifi-ap"), ports on the firewall–core link, a brace fan-out from the core, and a speed carried by a whole fan-out at once.

An HA firewall pair

digraph ha {
  inet [kind=internet, label="Internet"]
  fw1  [kind=firewall, label="FW-A",
        notes="HA primary"]
  fw2  [kind=firewall, label="FW-B",
        notes="HA secondary"]
  core [kind="l3-switch", label="CORE"]
  {rank=same; fw1 fw2}
  inet -> {fw1 fw2}
  fw1:e -> fw2:w [bundle=ha, link=lag,
                  label="HA sync"]
  fw1 -> core
  fw2 -> core
}

Rendered by Drawbridge v0.61.4 from the code above (light theme)Rendered by Drawbridge v0.61.4 from the code above (dark theme)

The rank=same group keeps the pair on one row; the sync link leaves A's east side and enters B's west, and bundle=ha draws it as an aggregate ring.

Campus with an MCLAG distribution pair

digraph campus {
  fw   [kind=firewall, label="FW-CAMPUS"]
  dist1 [kind="l3-switch", label="DIST-1"]
  dist2 [kind="l3-switch", label="DIST-2"]
  a1 [kind=switch, label="ACC-B1-01"]
  a2 [kind=switch, label="ACC-B1-02"]
  a3 [kind=switch, label="ACC-B2-01"]
  {rank=same; dist1 dist2}
  fw -> {dist1 dist2}
  dist1 -> dist2 [label="ISL", link=lag]
  dist1 -> {a1 a2 a3}
  dist2 -> {a1 a2 a3}
}

Rendered by Drawbridge v0.61.4 from the code above (light theme)Rendered by Drawbridge v0.61.4 from the code above (dark theme)

Dual-homed access switches, a declared distribution tier, and an ISL that is drawn between the peers without stacking them — the same shape a FortiLink MCLAG dump has, written by hand.

A spine–leaf fabric

digraph fabric {
  spine1 [kind="l3-switch", label="SPINE-1"]
  spine2 [kind="l3-switch", label="SPINE-2"]
  leaf1 [kind=switch, label="LEAF-1"]
  leaf2 [kind=switch, label="LEAF-2"]
  leaf3 [kind=switch, label="LEAF-3"]
  leaf4 [kind=switch, label="LEAF-4"]
  {rank=same; spine1 spine2}
  spine1 -> {leaf1 leaf2 leaf3 leaf4} [speed="100G"]
  spine2 -> {leaf1 leaf2 leaf3 leaf4} [speed="100G"]
}

Rendered by Drawbridge v0.61.4 from the code above (light theme)Rendered by Drawbridge v0.61.4 from the code above (dark theme)

Two fan-outs say the whole fabric. The spines share a row by declaration; the leaves land side by side beneath them on their own.

digraph wan {
  hq  [kind=firewall, label="FW-HQ"]
  br1 [kind=firewall, label="FW-BRANCH-1"]
  br2 [kind=firewall, label="FW-BRANCH-2"]
  mgmt [kind=server, label="MGMT-01"]
  ap  [kind="wifi-ap", label="AP-BR1"]
  hq -> br1 [link=ipsec, label="VPN",
             color="#7c3aed"]
  hq -> br2 [link=ipsec, label="VPN",
             color="#7c3aed"]
  hq -> mgmt [link=mgmt]
  br1 -> ap [link=wireless]
}

Rendered by Drawbridge v0.61.4 from the code above (light theme)Rendered by Drawbridge v0.61.4 from the code above (dark theme)

link= picks the connector style — IPsec tunnels, a management link, a wireless hop — and hex color= tints the strokes. Named colors would be ignored; hex is deliberate.

An inventory that fills the inspector

digraph assets {
  fw1 [kind=firewall, label="FW-CORE-1",
       mgmtIp="10.0.0.1",
       serial="FG100FTK00000001",
       model="FortiGate-100F",
       location="DC1 rack 3",
       notes="HA primary"]
  sw1 [kind="l3-switch", label="SW-CORE-1",
       mgmtIp="10.0.0.2",
       serial="S448DFTF00000011",
       model="FS-448D",
       location="DC1 rack 3"]
  srv1 [kind=server, label="ESX-01",
        mgmtIp="10.0.4.10",
        model="PowerEdge R650",
        location="DC1 rack 5"]
  fw1 -> sw1 -> srv1
}

Rendered by Drawbridge v0.61.4 from the code above (light theme)Rendered by Drawbridge v0.61.4 from the code above (dark theme)

Select any imported device and the inspector's asset fields are already filled — and they flow onward into the CSV inventory export.

An OT cell

digraph cell {
  scada [kind="scada-server", label="SCADA-01"]
  eng   [kind="engineering-workstation",
         label="ENG-01"]
  hmi1  [kind=hmi, label="HMI-LINE-1"]
  plc1  [kind=plc, label="PLC-LINE-1"]
  plc2  [kind="safety-plc", label="SAFETY-1"]
  io1   [kind="remote-io", label="IO-1"]
  {rank=same; scada eng}
  scada -> hmi1
  eng -> plc1
  hmi1 -> plc1 [link=conduit]
  plc1 -> io1 [link=fieldbus]
  plc1 -> plc2 [link=conduit]
}

Rendered by Drawbridge v0.61.4 from the code above (light theme)Rendered by Drawbridge v0.61.4 from the code above (dark theme)

The OT family — PLCs, HMIs, safety controllers, remote I/O — with conduit and fieldbus link styles.

The Purdue model as tiers

digraph purdue {
  subgraph cluster_l4 {
    purdue="4"
    erp   [kind=server, label="ERP"]
    fw_it [kind=firewall, label="FW-IT"]
  }
  subgraph cluster_idmz {
    purdue="3.5"
    hist_dmz [kind=historian,
              label="HIST-MIRROR"]
    jump [kind="jump-host", label="JUMP-OT"]
  }
  subgraph cluster_l3 {
    purdue="3"
    fw_ot [kind=firewall, label="FW-OT"]
    scada [kind="scada-server",
           label="SCADA-01"]
    hist  [kind=historian, label="HIST-01"]
    eng   [kind="engineering-workstation",
           label="ENG-01"]
  }
  subgraph cluster_l2 {
    purdue="2"
    hmi1 [kind=hmi, label="HMI-LINE-1"]
  }
  subgraph cluster_l1 {
    purdue="1"
    plc1 [kind=plc, label="PLC-LINE-1"]
    sis1 [kind="safety-plc", label="SIS-1"]
  }
  subgraph cluster_l0 {
    purdue="0"
    io1  [kind="remote-io", label="IO-1"]
    vfd1 [kind=vfd, label="VFD-1"]
    sio1 [kind="remote-io", label="SIS-IO-1"]
  }

  erp -> fw_it
  fw_it -> {hist_dmz jump}
  {rank=same; hist_dmz jump}
  hist_dmz -> fw_ot
  jump -> fw_ot
  fw_ot -> {scada hist eng}
  {rank=same; scada hist eng}
  scada -> hmi1
  hmi1 -> {plc1 sis1} [link=conduit]
  {rank=same; plc1 sis1}
  plc1 -> sis1 [link=conduit]
  plc1 -> {io1 vfd1} [link=fieldbus]
  sis1 -> sio1 [link=fieldbus]
}

Rendered by Drawbridge v0.61.4 from the code above (light theme)Rendered by Drawbridge v0.61.4 from the code above (dark theme)

Declaring purdue="N" on a cluster is what draws the Purdue backdrop itself: the import places the palette's Purdue-levels underlay behind the topology, sizes it so every band fits its devices, and seats each cluster's members inside their band — ERP and its firewall in level 4, the historian mirror and jump host in the industrial DMZ (3.5), site operations in 3, down to the process I/O in 0. {rank=same} still keeps pairs level within their band, and conduit/fieldbus mark the OT link types. The device's level is legible from its y-position alone — which is the whole point of the Purdue annotation.

Managed FortiLinks in current VDOM root:
        FortiLink interface : fortilink
digraph {
graph [layout = dot, rankdir = TB]
node [shape = rectangle, style = filled, color = grey]
//fgt cluster
node [fillcolor = red]
FG200FTK00000010
//tier 1
node [fillcolor = blue]
S448DFTF00000011
S448DFTF00000012
//tier 2+
node [fillcolor = green]
edge [color = grey, arrowhead=none]
FG200FTK00000010 -> {S448DFTF00000011 S448DFTF00000012} [color=black]
S448DFTF00000011 -> S448DFTF00000012
S448DFTF00000011 -> {S124EF0000000013}
S448DFTF00000012 -> {S124EF0000000014}
{rank=same; FG200FTK00000010}
{rank=same; S448DFTF00000012 S448DFTF00000011}
}

Rendered by Drawbridge v0.61.4 from the code above (light theme)Rendered by Drawbridge v0.61.4 from the code above (dark theme)

This is the real shape of execute switch-controller get-physical-conn dot fortilink output (fabricated serials), CLI chrome included. The fillcolor defaults carry the roles — red imports as a firewall, blue and green as switches — the serials fill the asset fields, and the multi-node rank=same keeps the MCLAG pair level while their ISL is drawn between them.

Generated by an AI

The prompt on the chapter's first page produced this from "a small clinic: reception, two exam rooms with wifi, a records server behind its own firewall":

digraph clinic {
  inet [kind=internet, label="Internet"]
  fw_edge [kind=firewall, label="FW-EDGE"]
  core [kind=switch, label="SW-CORE"]
  ap_recep [kind="wifi-ap", label="AP-RECEPTION"]
  ap_exam1 [kind="wifi-ap", label="AP-EXAM-1"]
  ap_exam2 [kind="wifi-ap", label="AP-EXAM-2"]
  fw_rec [kind=firewall, label="FW-RECORDS"]
  srv_rec [kind=server, label="SRV-RECORDS"]
  inet -> fw_edge -> core
  core -> {ap_recep ap_exam1 ap_exam2}
  core -> fw_rec -> srv_rec
}

Rendered by Drawbridge v0.61.4 from the code above (light theme)Rendered by Drawbridge v0.61.4 from the code above (dark theme)

Nothing exotic — which is the point: the format an AI reliably produces is the same one this whole chapter documents.