Builds DAG visualizations using ReactFlow v12 with custom nodes, ELKjs auto-layout, Zustand state management, and live state updates via WebSocket. Use when implementing workflow visualization dashboards, creating custom agent node components, integrating ELK layout algorithms, or wiring execution state into React components. Activate on "ReactFlow", "workflow visualization", "DAG visualization", "ELKjs", "custom nodes", "node-based editor", "graph visualization". NOT for writing Mermaid diagrams (use mermaid-graph-writer), general React development, or static diagram rendering.
Builds DAG visualizations using ReactFlow v12 with custom nodes, ELKjs auto-layout, Zustand state management, and live state updates via WebSocket. Use when implementing workflow visualization dashboards, creating custom agent node components, integrating ELK layout algorithms, or wiring execution state into React components. Activate on "ReactFlow", "workflow visualization", "DAG visualization", "ELKjs", "custom nodes", "node-based editor", "graph visualization". NOT for writing Mermaid diagrams (use mermaid-graph-writer), general React development, or static diagram rendering.
allowed-tools
Read,Write,Edit,Bash,Grep,Glob
metadata
{"tags":["reactflow","workflow-visualization","dag-visualization"],"pairs-with":[{"skill":"websocket-streaming","reason":"Live DAG state updates flow through WebSocket connections to ReactFlow visualizations"},{"skill":"human-gate-designer","reason":"Human approval gates are rendered as interactive ReactFlow custom nodes"},{"skill":"task-decomposer","reason":"Decomposed task DAGs are visualized as ReactFlow node graphs with ELKjs layout"}]}
Builds DAG visualizations using ReactFlow v12 with custom agent nodes, ELKjs auto-layout, Zustand state management, and live execution state updates.
Decision Points
State Management Strategy Selection
Graph Size <= 50 nodes?
├─ YES: Use useNodesState/useEdgesState hooks (simpler)
└─ NO: Use Zustand store
├─ Real-time updates required? → Include WebSocket integration
├─ Multi-component access? → Global Zustand store
└─ Complex interactions? → Add action methods (updateNodeData, bulkUpdate)
Layout Algorithm by DAG Shape
Node Count:
├─ < 20 nodes: Use 'layered' algorithm with direction='DOWN'
├─ 20-100 nodes: Use 'layered' with direction='RIGHT'
├─ > 100 nodes: Use 'stress' algorithm (better for large graphs)
└─ Highly connected (edges > 2x nodes): Use 'force' algorithm
Aspect Ratio:
├─ Wide dashboard: direction='RIGHT'
├─ Tall sidebar: direction='DOWN'
└─ Square viewport: Let ELK choose optimal direction
Custom Node Complexity Decision
Node Data Fields:
├─ Only status + name: Use built-in node types with custom styling
├─ 3-5 fields: Custom node with simple layout
├─ 6+ fields or nested data: Custom node with collapsible sections
└─ Interactive elements: Custom node + "nodrag" className on controls
Sync Strategy for Live Updates
Update Frequency:
├─ Real-time (< 1s): WebSocket with optimistic updates
├─ Frequent (1-10s): WebSocket with batching
├─ Periodic (> 10s): HTTP polling
└─ User-triggered: Manual refresh button
Data Size:
├─ Full DAG < 1MB: Send complete state
├─ Large DAG: Send delta updates (node ID + changed fields)
└─ Huge DAG: Implement viewport-based loading
Failure Modes
Infinite Re-render Loop
Symptom: Browser tab freezes, React DevTools shows constant re-renders
Detection: If nodeTypes object is defined inside component body
Fix: Move nodeTypes outside component or wrap in useMemo
Stale State Updates
Symptom: Node status changes don't appear visually, but store updates correctly
Detection: If mutating existing node objects instead of creating new ones
Fix: Always spread objects: { ...node, data: { ...node.data, newField } }
Layout Thrashing
Symptom: Nodes jump around constantly, poor performance with live updates
Detection: If ELK layout runs on every state change instead of topology changes
: Only trigger layout when nodes/edges are added/removed, not data updates
Fix
Handle Positioning Mismatch
Symptom: Edges connect to wrong positions or don't connect at all
Detection: If using v11 position properties (xPos, yPos) in v12
Fix: Update to v12 properties: positionAbsoluteX, positionAbsoluteY
Drag Interference
Symptom: Buttons/inputs inside custom nodes trigger node dragging
Detection: If interactive elements don't have proper event handling
Fix: Add className="nodrag" to all buttons, inputs, selects inside nodes
Zustand vs useState: Zustand handles 100+ node updates without re-rendering parent
ELK algorithm choice: 'layered' fast for < 100 nodes, 'stress' for larger graphs
WebSocket batching: Group status updates to avoid layout thrashing
Quality Gates
Functional Validation
ReactFlow component renders without console errors
All custom node types appear in nodeTypes registry
ELK layout completes within 2 seconds for target node count
WebSocket connections establish and receive test messages
Node data updates trigger visual changes within 200ms
Performance Thresholds
Initial render completes within 1 second for 50 nodes
Layout computation finishes within 3 seconds for 100 nodes
Memory usage stays under 100MB for 200-node graphs
Frame rate maintains 30fps during zoom/pan operations
WebSocket updates don't cause visible stuttering
Visual Quality Checks
Edges connect to correct handle positions (not node centers)
Node labels remain readable at 50% zoom level
Status colors match design system specifications
Interactive elements (buttons, inputs) don't trigger node dragging
fitView() centers graph with appropriate padding margins
Accessibility Requirements
All interactive nodes have proper ARIA labels
Keyboard navigation works for node selection
Color-based status indicators have text/icon alternatives
Focus indicators visible on custom node components
Screen reader announces node status changes
NOT-FOR Boundaries
Static Diagrams: For Mermaid flowcharts or architectural diagrams, use mermaid-graph-writer instead. ReactFlow is for interactive, live-updating visualizations.
Simple Charts: For bar charts, line graphs, or pie charts, use dedicated charting libraries (recharts, d3) instead. ReactFlow is specifically for node-edge graphs.
General React Development: For standard React components, forms, or layouts, use general React skills instead. This skill is ReactFlow-specific.
3D Visualizations: For 3D network graphs or spatial layouts, use three.js or WebGL libraries instead. ReactFlow is 2D-only.
Mobile-First Apps: For touch-first mobile interfaces, consider native gestures instead. ReactFlow is optimized for mouse/trackpad interaction.
Real-time Collaboration: For multi-user editing like Figma, use specialized real-time sync libraries instead. ReactFlow handles read-only live updates well but not collaborative editing.
Layout QA gate (mechanical — run before shipping)
Before calling any rendered page, artifact, dashboard, deck, or component done,
run the mechanical overflow/collision checker. It renders the page headlessly and
flags text-vs-text collisions, clipped/ellipsis-truncated elements, text escaping
its container, and horizontal page scroll — the visual defects a screenshot hides
and that only appear at a specific width or in one theme.
Resolve layout-overflow-guard from the active skill catalog before running it.
The command below shows the standard Claude install path; use the path reported
by your harness. If the skill is absent, install or sync it instead of skipping
this gate.
You do not need to read check_layout.py — invoke it with the Bash tool and
act on its report and exit code (non-zero = a defect). The script's source never
enters your context; only its findings do. Drive it to zero violations across
every width and both themes before you ship. Full detail: the
layout-overflow-guard skill.