Architecture & Roadmap
How the component is put together, why it's shaped that way, and where it's going. If you only render graphs you don't need this — start at Pipeline Graph.
Design principles
Four rules the whole component follows:
- Purely presentational.
PipelineGraphfetches nothing and traces nothing. Input is JSON (from thedl_traceservice) plus an optional live status overlay; output is pixels. This keeps it trivially embeddable and testable. - The graph is a derived view of code. Structure comes from the tracer, not from the UI. The component never mutates the graph — node drags are a local position overlay, not edits to the data.
- Runtime look is derived from one source of truth. An edge stores no
colour/width/animation; its flow is a pure function of its endpoints'
status. Push new statuses and every edge restyles itself — no edge diffing. - Selection is controlled or uncontrolled. Pass
selectedNodeId+onSelectNodeto own it (and sync the graph withPipelineSource), or omit both and the component tracks selection internally.
The file split
The component is five small modules, each with one job:
| Module | Responsibility |
|---|---|
types.ts | The data model — PipelineGraphData, GraphNode, GraphEdge, NodeStatus, StatusOverlay. Mirrors the tracer's JSON 1:1. |
flow.ts | The visual language — kindIcon (the card's leading glyph), kindColor (the thumbnail dot), STATUS, FLOW, and the derivations edgeFlow(src, dst) + portPos / portAlong. Colours are uikit tone tokens, so light/dark is automatic. |
edge-path.ts | Pure geometry — buildEdgePath routes a rounded orthogonal (Manhattan) edge that detours around intervening node boxes, falling back to a curve when endpoints are near-colinear. |
PipelineGraph.tsx | The canvas — pan/zoom, node drag, selection, the SVG edge + card render, and the per-pair param tags (drag to rebend an edge). |
PipelineSource.tsx | The paired read-only inspector — pipeline status + .py, or a selected node's status/i-o/schema/config/output, plus the run/review/continue/done button lifecycle. |
flow.ts is the shared vocabulary: edgeFlow and FLOW are exported from
@dreamlake/uikit, so a legend, a docs board, or a custom overlay can reuse the
exact same rules the canvas does — no reimplementation, no drift.
The render pipeline
One render of PipelineGraph, end to end:
- Merge overlays. Each node is combined with its
statusByIdentry (livestatus/progress/duration) and any local dragposOverride. The static graph is never mutated. - Size the world. Node positions set the scroll bounds; one
translate()+scale()transform on the content layer drives the nodes and the SVG edge layer together (so they never drift apart under pan/zoom). - Draw edges. For each edge:
portPosresolves theoutandinport coordinates →buildEdgePathroutes around obstacles →edgeFlow(src, dst)picks a flow →FLOW[flow]gives colour/width/dash/anim. Amaskedge stays dashed in the settled states so a gate always reads as a gate; the edges touching the selected node highlight in that node's status colour (not a fixed accent), while the rest fade back. - Place param tags. One tag per node-pair lists the params it transfers,
resting on the edge at its routed bend (
buildEdgePathreports the point, so the tag tracks the line through detours). Dragging a tag along the edge rebends it (a per-pairbendFrac); across it lifts the tag onto a leader. - Draw nodes. Absolutely-positioned cards, tinted by
status, with the kind's lucide glyph (kindIcon, tinted bystatus— shape means type, colour means state), theinputs→outputsmeta, a status footer (pulsing whenrunning), and a single input dot (left-centre) / output dot (right-centre) — every parameter shares the one input dot; its names live in the param tag. - Overlay chrome (
showControls, default on). The legend (top-right) and the keyboard-hint strip (bottom). The legend has two sections: nodes — the kind glyphs, drawn neutral and listing only the kinds present on this canvas (NodeKindis open-ended, so a fixed list would either miss a graph's kinds or pad the key with rows you can't see) — and edges, rendered from the sameFLOW. PassshowControls={false}to drop both for tiny embeds.
Interaction: background drag pans; ⌘/ctrl-wheel or pinch zooms about the
cursor; plain wheel / two-finger drag pans; a node drag writes to posOverride
(cleared when graph.id changes); a click without a drag toggles selection; a
tag drag rebends its edge or lifts the tag onto a leader.
What it deliberately leaves out
Faithful to the design prototype's look, but intentionally simpler than its full canvas — these are conscious omissions, not bugs:
- Param tags, not per-edge flow-label chips. The prototype floats a draggable flow-state chip at each edge's midpoint; here a tag instead names the params a node-pair transfers (dragging it rebends the edge), and the flow vocabulary lives in the legend.
- No auto-fit, no vertical layout mode. Positions come from the tracer's layout; the user pans/zooms/drags nodes.
- No vim marks (the
a–zjump labels). Arrow/hjklselection navigation is supported — see Current stage. - No edge inspector. Clicking selects nodes, not edges — that's still a roadmap item below.
Current stage
Shipping today:
- ✅ Pure, theme-aware renderer — dotted canvas, status-tinted cards, obstacle- routed edges, pan/zoom/drag, controlled or uncontrolled selection.
- ✅ Keyboard navigation (focus-scoped) — ↑/↓ (or k/j) step the selection in topological order, ←/→ (or h/l) hop to the upstream/downstream neighbour, Esc clears; the selected node pans into view.
- ✅ Connector tags (
data/mask) and connector states (the six derived flows), catalogued in Anatomy. - ✅ Per-pair param tags — one tag per node-pair naming the params it transfers, resting on its edge; drag it to rebend the edge or lift it onto a leader.
- ✅ Status-driven highlights — selecting a node tints its card and touching edges in the node's own status colour, not a fixed accent.
- ✅ Live animation from a
statusByIdoverlay — structure stays static, status streams in, edges re-derive their flow. - ✅
PipelineSourceinspector — contextualPIPELINE/NODE/CODEtabs: pipeline status +.py, or a selected node's status pill, resolved i/o, schema,config, and a sampled output preview table. - ✅ Run lifecycle —
onRun/running/reviewNodeId/doneandonContinuedrive the rail's▶ RUN→running…→⏸ REVIEW/✓ DONE(and▶ CONTINUEon a waiting review node) buttons; execution stays the host's.
Roadmap
Richer output previews (next)
The node inspector's output panel renders a tabular
NodePreview (schema +
sampled rows) today. The design prototype's PipeOutputTab also previews other
modalities — an image-grid of frame thumbnails, a text-grid of label
previews — keyed off a per-modality output artifact; wiring those up is the
next step, so a running vision or labeling node shows its real samples inline.
Further out
- Edge inspector — click an edge for its flow, throughput (
rows/duration), and, onerror, the failing stage's traceback. - Tag collision avoidance — tags rest on the edge today; auto-nudging crowded ones clear of each other (prototype parity).
- Auto-fit on mount/resize and a vertical layout direction.
- Job / fleet views — the running-jobs and compute-fleet panels that pair with the graph in Studio.
Back to: Pipeline Graph · Anatomy · Pipeline Graph JSON.