How layout is chosen
The six archetypes, the exact rules that select one, the routing and tidy passes, and the geometry linter that gates the build.
You don't pick a layout. Marrow classifies the topology into one of six archetypes, computes a single layout for it, and lints the result. This page gives the actual rules so you can predict — and control — the outcome.
The pipeline
The chosen archetype is shown in every diagram's sidebar under About → Layout, so you can always check what the engine decided.
Classification, in precedence order
Rules are evaluated top to bottom; the first match wins. Declared structure always outranks inferred shape.
1. zoned — two or more zones contain devices
Each zone is laid out independently and the results are packed into a mosaic. This is the strongest signal available; if you want zones, this is how you get them.
2. tiered — every device declares a tier
ELK layered with tier partitions, edge at the top through endpoint at the bottom. One device missing a tier disqualifies the whole topology.
3. ring — a single cycle
Requires 4+ devices, the graph connected, and every device having exactly two neighbors. Placed on a circle.
4. hub-spoke — one or two devices own the links
Requires 4+ devices. The engine takes the one or two highest-degree devices (each needing degree ≥ 3) as hubs, then demands purity: every non-hub device must connect exclusively to hubs.
A single spoke-to-spoke link disqualifies the entire topology from hub-spoke and drops it to layered. This is the rule that surprises people most. If you want the radial branch-office look, the branches must not talk to each other in the file — even if they do in real life.
Hubs sit at the center; spokes are placed on a ring whose radius is derived from the actual widths of the spoke nodes, so the arrangement is symmetric and overlap-free by construction rather than by a fixed device count.
5. mesh — small and dense
At most 16 devices, edge density ≥ 0.4, average degree ≥ 3. Circular placement with polyline routing.
6. flat — everything else
Plain ELK layered.
Getting the shape you want
| You want | Declare |
|---|---|
| Buildings / sites side by side | ≥ 2 zones with devices in them |
| Classic top-down hierarchy | tier on every device |
| Radial WAN / branch view | 1–2 hubs, spokes touching only hubs |
| A ring | Exactly two neighbors per device, connected |
| A dense fabric | ≤ 16 devices, well-connected |
If the layout is wrong, the description is wrong. Change what you declare, not where things sit.
Routing and the tidy pass
Placement decides where nodes go; routing decides how cables get between them. Marrow routes orthogonally with libavoid, then runs a tidy pass that applies cable-tray discipline — the principle that no line owns a free path:
- Coincident parallels. Multiple links between the same pair are routed on one visible stroke. A plain parallel run carries an
×Ncount; when the members share alagid the run is chipped with that id instead (PO1), since the bundle has a name. Each link keeps its own identity for hover and status. - Gutter buses. When a parent feeds three or more children in the row below, the fan-out is rerouted onto a shared lane: parent spine → horizontal lane → taps. Lanes are claimed per gutter with collision guards; any channel that would clip a node falls back to its original route.
- Draw order. Healthy edges draw first so alarms sit on top of shared runs.
- Level of detail. Leaf links (endpoint tier) fade at far zoom, so the zoomed-out view reads trunks and structure.
Tidy applies to zoned, tiered, and flat archetypes. Radial shapes keep their spokes.
The effect is large: on a real HQ zone, 165 links collapsed to 36 unique geometries. "Never crosses" is impossible for non-planar graphs — channels are the answer instead.
The geometry linter
The scene is checked before anything is rendered.
| Level | Meaning | Examples |
|---|---|---|
| L1 | Fails the build | Node overlap on label-inclusive boxes; edge segments crossing foreign node interiors; endpoints not touching their node's box; port chips overlapping |
| L2 | Auto-repaired | Fixable geometry defects |
| L3 | Advisory | Excessive crossings, extreme aspect ratio |
An L1 failure is not a warning you can ignore — the build stops. That's deliberate: a diagram with overlapping nodes is worse than no diagram, and the guarantee "output is never overlapping" is only worth something if it's enforced. See ADR-0007.
Pinning
pin: { x: 100, y: 200 } fixes a device's position. It exists for the rare case
where a physical arrangement genuinely matters — a rack elevation, a
geographically meaningful layout.
Treat it as a last resort. Pins bypass the placement engine, so they can produce the overlaps the linter then refuses to build, and they rot the moment the topology changes around them. If you find yourself pinning more than a couple of devices, the structure you declared is probably not the structure you meant.
Legacy x-v1-config
Files brought forward by marrow import may carry an x-v1-config: block with
engines:, layouts:, and output_filename:. It is inert. Version 1
rendered one variant per engine × layout combination; v2 has no such mode and
never reads the block. Delete it when you see it — it has zero effect and
misleads readers into expecting multiple layouts.