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

  topology
     │
     ▼
  classify   ── one of: zoned · tiered · ring · hub-spoke · mesh · flat
     │
     ▼
  size       ── measure every node, labels included (deterministic glyph tables)
     │
     ▼
  place      ── ELK layered  (zoned, tiered, flat)
                compose      (zone mosaic packing)
                polar        (hub-spoke)
                circle       (ring, mesh)
     │
     ▼
  route      ── libavoid orthogonal routing, or polylines for radial shapes
     │
     ▼
  tidy       ── merge coincident runs, pull fan-outs onto gutter buses
     │
     ▼
  lint       ── L1 fails the build · L2 auto-repairs · L3 advises
     │
     ▼
  scene      ── boxes + polylines, handed to the renderers

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. tieredevery 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.

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.

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 wantDeclare
Buildings / sites side by side≥ 2 zones with devices in them
Classic top-down hierarchytier on every device
Radial WAN / branch view1–2 hubs, spokes touching only hubs
A ringExactly 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 ×N count; when the members share a lag id 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.

LevelMeaningExamples
L1Fails the buildNode overlap on label-inclusive boxes; edge segments crossing foreign node interiors; endpoints not touching their node's box; port chips overlapping
L2Auto-repairedFixable geometry defects
L3AdvisoryExcessive 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.