Connector nodes: bindable arrows between shapes

Author: Ed-KeyCreated Aug 31, 2026Updated Sep 18, 2026

Problem

FigJam connectors do not survive OpenPencil today. CONNECTOR is in the node-type enum (packages/scene-graph/src/types.ts, kiwi type 19), but import and paste filter it as a non-visual type (NON_VISUAL_TYPES in packages/core/src/clipboard.ts), no binding fields (connectorStart / connectorEnd / magnets) exist anywhere in the model, and nothing renders or edits them. Pasting a FigJam flow keeps the boxes and silently drops every arrow.

Beyond imports, diagram and wireframe users want the Figma/Canva interaction: drag from one shape to another, get an arrow that stays attached when either shape moves.

Proposed direction

Follow Figma's data model so .fig round-trip stays natural:

  • Scene graph: connector data on the node: connectorStart / connectorEnd as { endpointNodeId, magnet: AUTO | TOP | BOTTOM | LEFT | RIGHT } or { position } for a free end, plus connectorLineType (STRAIGHT first, ELBOWED later) and end caps reusing the arrow-cap rendering from #615.
  • Derived geometry: connector shape recomputed from the current bounds of bound nodes (resolve the anchor, clip at the shape edge with a small gap, route, place the head), invalidated when a bound node moves or resizes; a deleted target unbinds that end to a fixed position.
  • Rendering: draw the routed path through the existing stroke pipeline plus the arrow-cap heads.
  • Import/paste: stop filtering CONNECTOR, decode endpoint bindings, and render statically even before any interaction exists.
  • Editing: a connector tool (drag from a shape edge to another shape), magnet highlights on hover, endpoint re-drag to re-bind. MCP and design-JSX surfaces (create_connector, <Connector>) so agents can build flow diagrams programmatically.

Phasing

  1. Schema + import + static rendering, so FigJam connectors survive and draw.
  2. Live re-routing on bound-node changes, plus MCP tools.
  3. Connector tool UX (magnets, previews), elbow routing, text labels.

I am happy to build this as a series of focused PRs if the direction works for you, and would appreciate guidance on where the derive pass should live and any constraints on scene-graph additions.