Learn / Edges & routing
Edges & routing
An edge stores intent — connect A to B, orthogonally, avoiding obstacles — and the renderer turns intent into geometry that stays correct as nodes move. Only two fields are required.
The minimal edge, and every field after it
{ source: 'a', target: 'b' } // that's a complete edge
{ id: 'e1',
source: 'a', target: 'b', // node ids
sourceHandle: 'out', // a port id — or a bare side: 'right'
targetHandle: 'left',
type: 'orthogonal', // 'direct' | 'smooth' | 'orthogonal' | 'bezier'
router: 'avoid', // 'straight' | 'orthogonal' | 'manhattan' | 'avoid' | 'elk'
connector: 'rounded', // corner treatment: 'straight' | 'rounded' | 'smooth' | 'bezier'
label: 'retry',
style: { stroke: '#9333ea', strokeWidth: 2, strokeDasharray: '6 3' },
data: { weight: 3 }, // your payload
points: [{ x: 340, y: 180 }] } // explicit waypoints — restores a user-edited route
Omit both handles and the edge attaches to whichever default port faces its partner
as nodes move. Default ports have deterministic ids
(<nodeId>__top … __left), which is why a bare side name
like sourceHandle: 'bottom' resolves. For true perimeter floating —
attaching anywhere along the node's outline rather than at a port — set
metadata: { connectionPoint: 'smart' }.
Type versus router — two different questions
type answers "what shape is the line" (straight segments, one smooth
curve, right angles, a bezier). router answers "which path does it take"
— and that is where the interesting engineering lives:
| Router | Behavior |
|---|---|
straight | direct line, endpoints only |
orthogonal | right-angled path from the port's exit direction |
manhattan | grid-based right-angle routing with turn minimization |
avoid | obstacle avoidance — the path walks around nodes instead of crossing them, and re-routes live as you drag |
elk | edge routes computed by the ELK layout engine, consistent with an ELK-laid-out graph |
Live: every edge type, router and connector →
Labels, parallel edges, crossings
label puts editable text on the path (double-click to edit in place;
drag to reposition — the position persists in the model). When several edges connect
the same pair of nodes, the renderer fans them apart
(rendererConfig: { parallelLinks: true, parallelSpacing: 12 }), and where
unrelated edges cross you can render jump-overs via the renderer config's jump
styles.
Reconnecting and editing
Drag an edge's endpoint and drop it on another port — validators run again (see
Ports & validation; the candidate carries
link so a rule can treat reconnection differently). Drag the path itself
to bend it — the bend lands in points and round-trips through
serialization. Every one of these edits is a single undoable step.
Where next
- Ports & validation — what edges attach to.
- Layout — edge routes that come from the layout engine.