Output shapes

A single self-contained file, or a multi-page site — what triggers each, what's inside, and the guarantees both hold to.

marrow build produces one of two shapes. You don't choose; the topology's size does — with one override.

npm run build input/branch.yaml                # let the planner decide
npm run build -- input/branch.yaml --single    # force one file (-- : flag ahead)
npm run build -- input/branch.yaml -o dist/net.html

The threshold

  devices > 150  OR  top-level zones with devices > 5   →  multi-page site
  otherwise                                             →  single file

Both are checked; either one trips it. Five zones is fine, six is a site.

Single file

One .html in output/. Styles, the ~20 KB runtime client, and the icon sprites for the icons you actually used are all inlined.

Best for: anything you want to attach to a ticket, mail to a vendor, drop in a Confluence page, or open from a USB stick on a plane.

Multi-page site

A directory:

  output/global-enterprise/
  ├── index.html              overview — zones as summary tiles
  ├── zones/
  │   ├── campus.html         one page per TOP-LEVEL zone (covers its subtree)
  │   └── dc-east.html
  ├── devices/
  │   ├── core-sw-01.html     device-360 pages
  │   └── dist-sw-01.html
  ├── inventory.html          sortable, paginated table of everything
  └── assets/
      ├── styles.css
      ├── runtime.js
      └── search-data.js      cross-page search index

Also fully offline — file:// works, no server required.

Which zones get pages

Only top-level zones — a zone with no parent. Its page covers its entire subtree. So nesting depth is how you control page granularity: if emea > london > ldn-dc1 is your hierarchy, you get one emea page, not three.

Which devices get pages

A device earns a dedicated page if it is:

  • tier core, distribution, or edge — the infrastructure that people look up, or
  • carrying a note, or
  • carrying a config

Which is a good reason to write notes: documentation is what promotes a device to its own page.

Ghost nodes

A link that crosses a page boundary terminates in a dimmed, dashed "ghost" stub that navigates to the device's own page. Nothing is silently dropped at a page edge.

At scale

The multi-page shape exists so that no single page grows with the network. A device page carries its own neighborhood, the shared assets are written once, and everything else is another file you never load until you open it. That holds all the way up.

The reference topology — a fictional global enterprise, the At scale demo on the home page — is the stress test:

Devices · links · zones15,591 · 18,812 · 1,017
Sites194
Pages emitted15,775 (194 zone · 15,579 device · overview · inventory)
Total output~2.4 GB on disk
A device page~140 KB — ~12 KB gzipped, which is what a host serves
Build time~3 minutes

Two things that matter in practice:

Served size ≠ disk size. Pages are near-identical structurally, so gzip/brotli — which every static host applies — collapses them hard. The 2.4 GB on disk is a git-and-deploy concern, not a bandwidth one.

Very large builds need more heap. Node's default heap tops out somewhere around this size and the build aborts with an out-of-memory error. Raise it for the run:

NODE_OPTIONS=--max-old-space-size=12288 npm run build -- input/global-enterprise.yaml

Scale the number with the topology (~12 GB comfortably covers 15k devices). Small and mid-size networks never need this.

Guarantees, both shapes

Deterministic. The same YAML produces byte-identical output. Commit built diagrams and the diff is empty unless the network changed. Content-hashed page builds mean a rebuild only touches pages whose inputs moved.

Overlap-free. The geometry linter runs before render; an L1 defect fails the build rather than shipping a broken picture.

Self-contained. No network requests when opened. No CDN, no web fonts, no telemetry, no analytics. brand.link and brand.github are hyperlinks a reader may click — they are not loads.

Rendering tiers

Under the hood there are two renderers, chosen by size:

  • Hero tier — SVG. Full fidelity, crisp at any zoom, exportable to SVG.
  • Scale tier — a canvas host. Used when the node count would make SVG unusable.

Both draw the same scene and are kept visually identical; you shouldn't be able to tell which one you got except by the device count.

Publishing

The output is just files:

# static host
aws s3 sync output/global-enterprise s3://docs-bucket/network/

# or commit it next to your docs
cp output/branch.html docs/network/branch.html

For embedding in an existing docs site or wiki, see Embedding diagrams.