Skip to content

fix(layout): keep the flow readable on hubs, replies and groups that feed each other - #52

Merged
hyamero merged 14 commits into
stagingfrom
fix/layout-flow
Oct 3, 2026
Merged

hyamero merged 14 commits into
stagingfrom
fix/layout-flow

Conversation

@hyamero

@hyamero hyamero commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Architecture and dataflow layouts broke down on common shapes: a request handler calling many cards, a client that sends a request and shows the reply, groups that feed each other. The entry call wrapped round the whole diagram, edges of every colour left a card from one shared point, and labels piled up on the shared line far from what they named.

Layout

  • Replies and loops lay out against the flow. return edges, and any edge that closes a cycle (found by a walk from the entry points in draft order), are laid out reversed. The caller stays upstream of what it calls.
  • Edges that still end up running backwards are flipped and the layout is redone once. This happens when two groups feed each other. Such an edge now leaves and enters by the facing sides instead of wrapping round the diagram.
  • Trunks per style. A card's edges of one tone and line style leave (or arrive) as one trunk; another tone or line style gets its own port, so colours never hide each other. ELK orders the ports along the side.
  • Labels sit by the card they name.
    • On a fan-out a label sits by its target; on a fan-in, by its source. A spot only counts if the label is nearer its own edge than any other.
    • A label goes on a run its edge has to itself before it settles beside a trunk the edge shares, where it could name any of the trunk's edges. Across the corpus this moves 5 of the 16 labels that sat beside a trunk; the other 11 belong to edges with no run of their own long enough.
    • Labels keep off group frames and their titles.
    • When a label has no clear spot, the layout tries wider layer gaps, and wider gaps with longer straight runs into cards, and keeps whichever result seats labels best. This is skipped past 60 nodes.
  • Top-down rows are top-aligned, so a short card no longer sits centred on a taller neighbour.
  • Straight lines stay straight. ELK places ports at thirds of a side, which left runs slanted by a third of a pixel and drawn soft; routes are squared to whole pixels. Two ports less than 16px out of line are drawn as one straight line instead of a shallow step, by sliding an end no other edge shares along its side.

Viewer

  • Handle dots are drawn where each edge meets its card, as swimlane layouts already did.
  • Where lines cross, the line passing under gets a short break, so a crossing can't be mistaken for a branch joining a trunk. Every edge of a trunk breaks together. The main flow stays whole, and between equals a lone line breaks rather than a trunk. A break is cut with a mask, so it works over group fills, and it isn't drawn while the line crossing over is faded.
  • Below 50% zoom, where an 11px label renders under about 5.5px and can't be read, edge labels fade out. Labels on edges lit by a selection or trace stay. Exports always include every label, whatever the zoom.

Before and after

Each image shows the whole diagram, then a close-up of what changed.

A label moves off a shared trunk. "lookup" (orders to users) used to sit by the line into users that it shares with gateway to users. It now sits on its own run.
mesh

More labels move off shared lines. "consume" and "SMS" now sit on runs of their own edge.
food delivery

A shallow step becomes a straight line. "payment facts" ran between two ports 14px out of line.
event stream

A break where lines cross. The grey trunk breaks where the white main flow crosses it, so the crossing can't be read as a junction.
hub

Validation and skill

  • New warning semantics/duplicate-row-label.
  • The authoring contract now covers flow order, marking replies as return, busy cards, and one row per label.

Tests

  • New stress set (packages/layout/test/stress.ts, made-up diagrams): hub top-down and left-to-right, fan-in, cycle, nested groups, two-way pairs, mesh, self-loop, staged compact, single, pair.
  • New quality checks over every shipped diagram plus the stress set (quality.test.ts): no port shared by edges that look different, every edge enters its target from the facing side, no long detours, every segment along an axis, no shallow step between ports.
  • Label checks extended to frames, titles and nearest-edge, and to the stress set.
  • Fuzz: 200 random architecture and dataflow diagrams checked for the same properties, plus orthogonal routes that never cross other cards.
  • Visual baselines refreshed for the viewer's handle dots.

Across 31 diagrams (shipped samples and examples plus the stress set):

Metric Before After
Edge length drawn on top of another edge 88,927px 26,357px
Ports mixing tones or line styles 43 0
Labels nearer another edge than their own 5 0
Summed worst detour 40.8 27.3
Bends 400 350
Crossings 13 24 (the old trunk hid most of these by drawing edges on top of each other)

Trade-offs

  • Where several cards feed the same targets, trunks make it less obvious which line goes where; selecting a card lights its own edges.
  • Diagrams past 60 nodes lay out more slowly: about 5s at 120 nodes, against about 2s before. Up to 60 nodes it stays under a second.

@vercel

vercel Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
stackmap-site Ready Ready Preview Oct 3, 2026 10:10am UTC

@hyamero
hyamero merged commit 0f3b912 into staging Oct 3, 2026
7 checks passed
@hyamero
hyamero deleted the fix/layout-flow branch October 3, 2026 15:27
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 0.4.0-rc.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 0.4.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

This branch was successfully deployed

1 active deployment
Preview — 84a3e870 Deployed Oct 3, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant