Skip to content
Development
Skill

/react-flow-architecture

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.

From plugin
beagle
82139 skills2 commands
Install
$ npx -y skills add existential-birds/beagle --skill react-flow-architecture --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/react-flow-architecture

Context preview

The summary Claude sees to decide when to auto-load this skill.

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.

SKILL.md

react-flow-architecture.SKILL.md
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)

// 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)

// 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

// 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)

// 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

// 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

// 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

import dagre from 'dagre';

function getLayoutedElements(nodes: Node[], edges: Edge[]) {
  const g = new dagre.graphlib.Graph();
  g.setGraph({ rankdir: 'TB' });
  g.setDefaultEdgeLabel(
Read more
Ships withbeagle

Image: NASA, Public Domain. Source Beagle is an Agent Skills marketplace: framework-aware code review, documentation, testing, architectural analysis, and git workflows for any compatible coding agent.

Get the whole plugin

Other skills on beagle.