react-flow-architecture — Claude Code skill: install
Architecture guidance for React Flow node-based UIs, covering state, integrations, scale and fit decisions.
npx skills add existential-birds/beagle --skill react-flow-architecture -a claude-codeWhat react-flow-architecture does
This skill helps plan applications built around React Flow nodes and edges. It covers workflow builders, visual programming tools, diagrams, data pipelines, mind maps, decision trees and state-machine editors. Before implementation, it walks through user interactions, graph scale, state placement and the choice between React Flow and listed alternatives.
The guidance includes local hooks, Zustand and Redux patterns, change handlers, nested sub-flows, viewport persistence, API loading and dagre layout. For 100–500 nodes, it recommends onlyRenderVisibleElements; above 1000 nodes, virtualization or WebGL-based tools deserve consideration. Simple static diagrams are a case for direct SVG or canvas work.
What it helps with
- choose React Flow for a node-based UI
- place node and edge state
- design nested node groups
- persist the graph viewport
- plan scaling for large graphs
Example prompts for the agent
- Design a workflow editor with React Flow and run the four architecture checks before implementation.
- Compare local state, Zustand and Redux for managing
nodesandedges. - Show how to save and restore
nodes,edgesandviewportwithuseReactFlow.
How to install react-flow-architecture
1Skills CLI (Vercel)
npx skills add existential-birds/beagle --skill react-flow-architecture -a claude-code2Manually: put the files in place
~/.claude/skills/react-flow-architecture/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/react-flow-architecture/
1Skills CLI (Vercel)
npx skills add existential-birds/beagle --skill react-flow-architecture -a codex2Manually: put the files in place
.agents/skills/react-flow-architecture/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add existential-birds/beagle --skill react-flow-architecture -a cursor2Manually: put the files in place
.cursor/skills/react-flow-architecture/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install existential-birds/beagle react-flow-architecture2Manually: put the files in place
.github/skills/react-flow-architecture/SKILL.md1Skills CLI (Vercel)
npx skills add existential-birds/beagle --skill react-flow-architecture -a gemini-cli2Platform CLI
gemini skills install https://github.com/existential-birds/beagle --path plugins/beagle-react/skills/react-flow-architectureManually: put the files in place
.devin/skills/react-flow-architecture/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add existential-birds/beagle --skill react-flow-architecture -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about react-flow-architecture
How do I install react-flow-architecture in Claude Code?
Run npx skills add existential-birds/beagle --skill react-flow-architecture -a claude-code, then check ~/.claude/skills/react-flow-architecture/SKILL.md.
What does react-flow-architecture do?
It gives architectural guidance for React Flow projects, including state choices, API integration, nested sub-flows, viewport persistence and performance planning.
Can React Flow handle a large graph?
For 100–500 nodes, the skill recommends onlyRenderVisibleElements. Above 1000 nodes, it points to virtualization or WebGL options such as Sigma.js.
Source text
SKILL.md · Apache-2.0
---
name: react-flow-architecture
description: Architectural guidance for building node-based UIs with React Flow. Use when designing flow-based applications, making decisions about state management, integration patterns, or evaluating whether React Flow fits a use case.
---
# React Flow Architecture
## When to Use React Flow
### Good Fit
- Visual programming interfaces
- Workflow builders and automation tools
- Diagram editors (flowcharts, org charts)
- Data pipeline visualization
- Mind mapping tools
- Node-based audio/video editors
- Decision tree builders
- State machine designers
### Consider Alternatives
- Simple static diagrams (use SVG or canvas directly)
- Heavy real-time collaboration (may need custom sync layer)
- 3D visualizations (use Three.js, react-three-fiber)
- Graph analysis with 10k+ nodes (use WebGL-based solutions like Sigma.js)
### Decision workflow (gates)
Run this sequence before locking the stack or sprinting implementation. Skip only for throwaway prototypes.
1. **Name the interactions** — List the top user actions (e.g. drag, connect, delete, group). **Pass:** Each action maps to a concrete React Flow callback you will implement (`onNodesChange`, `onConnect`, …).
2. **Classify scale** — Estimate peak nodes (visible canvas or document total). **Pass:** Your range matches a row in [Node Count Guidelines](#node-count-guidelines) and you accept the listed strategy (e.g. `onlyRenderVisibleElements` when that row implies it).
3. **Place state** — Choose local hooks, an external store, or Redux/other. **Pass:** One sentence states where persistence, undo, or cross-surface sync will live, or explicitly “not needed yet.”
4. **Re-check alternatives** — If the use case matches [Consider Alternatives](#consider-alternatives), **Pass:** One sentence explains why React Flow still fits or which listed alternative you chose instead.
## Architecture Patterns
### Package Structure (xyflow)
```
@xyflow/system (vanilla TypeScript)
├── Core algorithms (edge paths, bounds, viewport)
├── xypanzoom (d3-based pan/zoom)
├── xydrag, xyhandle, xyminimap, xyresizer
└── Shared types
@xyflow/react (depends on @xyflow/system)
├── React components and hooks
├── Zustand store for state management
└── Framework-specific integrations
@xyflow/svelte (depends on @xyflow/system)
└── Svelte components and stores
```
**Implication**: Core logic is framework-agnostic. When contributing or debugging, check if issue is in @xyflow/system or framework-specific package.
### State Management Approaches
#### 1. Local State (Simple Apps)
```tsx
// useNodesState/useEdgesState for prototyping
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
```
**Pros**: Simple, minimal boilerplate
**Cons**: State isolated to component tree
#### 2. External Store (Production)
```tsx
// Zustand store example
import { create } from 'zustand';
interface FlowStore {
nodes: Node[];
edges: Edge[];
setNodes: (nodes: Node[]) => void;
onNodesChange: OnNodesChange;
}
const useFlowStore = create<FlowStore>((set, get) => ({
nodes: initialNodes,
edges: initialEdges,
setNodes: (nodes) => set({ nodes }),
onNodesChange: (changes) => {
set({ nodes: applyNodeChanges(changes, get().nodes) });
},
}));
// In component
function Flow() {
const { nodes, edges, onNodesChange } = useFlowStore();
return <ReactFlow nodes={nodes} onNodesChange={onNodesChange} />;
}
```
**Pros**: State accessible anywhere, easier persistence/sync
**Cons**: More setup, need careful selector optimization
#### 3. Redux/Other State Libraries
```tsx
// Connect via selectors
const nodes = useSelector(selectNodes);
const dispatch = useDispatch();
const onNodesChange = useCallback((changes: NodeChange[]) => {
dispatch(nodesChanged(changes));
}, [dispatch]);
```
### Data Flow Architecture
```
User Input → Change Event → Reducer/Handler → State Update → Re-render
↓
[Drag node] → onNodesChange → applyNodeChanges → setNodes → ReactFlow
↓
[Connect] → onConnect → addEdge → setEdges → ReactFlow
↓
[Delete] → onNodesDelete → deleteElements → setNodes/setEdges → ReactFlow
```
### Sub-Flow Pattern (Nested Nodes)
```tsx
// Parent node containing child nodes
const nodes = [
{
id: 'group-1',
type: 'group',
position: { x: 0, y: 0 },
style: { width: 300, height: 200 },
},
{
id: 'child-1',
parentId: 'group-1', // Key: parent reference
extent: 'parent', // Key: constrain to parent
position: { x: 10, y: 30 }, // Relative to parent
data: { label: 'Child' },
},
];
```
**Considerations**:
- Use `extent: 'parent'` to constrain dragging
- Use `expandParent: true` to auto-expand parent
- Parent z-index affects child rendering order
### Viewport Persistence
```tsx
// Save viewport state
const { toObject, setViewport } = useReactFlow();
const handleSave = () => {
const flow = toObject();
// flow.nodes, flow.edges, flow.viewport
localStorage.setItem('flow', JSON.stringify(flow));
};
const handleRestore = () => {
const flow = JSON.parse(localStorage.getItem('flow'));
setNodes(flow.nodes);
setEdges(flow.edges);
setViewport(flow.viewport);
};
```
## Integration Patterns
### With Backend/API
```tsx
// Load from API
useEffect(() => {
fetch('/api/flow')
.then(r => r.json())
.then(({ nodes, edges }) => {
setNodes(nodes);
setEdges(edges);
});
}, []);
// Debounced auto-save
const debouncedSave = useMemo(
() => debounce((nodes, edges) => {
fetch('/api/flow', {
method: 'POST',
body: JSON.stringify({ nodes, edges }),
});
}, 1000),
[]
);
useEffect(() => {
debouncedSave(nodes, edges);
}, [nodes, edges]);
```
### With Layout Algorithms
```tsx
import dagre from 'dagre';
function getLayoutedElements(nodes: Node[], edges: Edge[]) {
const g = new dagre.graphlib.Graph();
g.setGraph({ rankdir: 'TB' });
g.setDefaultEdgeLabel(() => ({}));
nodes.forEach((node) => {
g.setNode(node.id, { width: 150, height: 50 });
});
edges.forEach((edge) => {
g.setEdge(edge.source, edge.target);
});
dagre.layout(g);
return {
nodes: nodes.map((node) => {
const pos = g.node(node.id);
return { ...node, position: { x: pos.x, y: pos.y } };
}),
edges,
};
}
```
## Performance Scaling
### Node Count Guidelines
| Nodes | Strategy |
|-------|----------|
| < 100 | Default settings |
| 100-500 | Enable `onlyRenderVisibleElements` |
| 500-1000 | Simplify custom nodes, reduce DOM elements |
| > 1000 | Consider virtualization, WebGL alternatives |
### Optimization Techniques
```tsx
<ReactFlow
// Only render nodes/edges in viewport
onlyRenderVisibleElements={true}
// Reduce node border radius (improves intersect calculations)
nodeExtent={[[-1000, -1000], [1000, 1000]]}
// Disable features not needed
elementsSelectable={false}
panOnDrag={false}
zoomOnScroll={false}
/>
```
## Trade-offs
### Controlled vs Uncontrolled
| Controlled | Uncontrolled |
|------------|--------------|
| More boilerplate | Less code |
| Full state control | Internal state |
| Easy persistence | Need `toObject()` |
| Better for complex apps | Good for prototypes |
### Connection Modes
| Strict (default) | Loose |
|------------------|-------|
| Source → Target only | Any handle → any handle |
| Predictable behavior | More flexible |
| Use for data flows | Use for diagrams |
```tsx
<ReactFlow connectionMode={ConnectionMode.Loose} />
```
### Edge Rendering
| Default edges | Custom edges |
|---------------|--------------|
| Fast rendering | More control |
| Limited styling | Any SVG/HTML |
| Simple use cases | Complex labels |
© existential-birds · Apache-2.0 · existential-birds/beagle