Diagrams
Node-based diagrams with XYFlow (React Flow) — flow charts, mind maps, and interactive node editors.
Read this when adding diagram features to your app.
Useful for workflow builders, mind maps, or visual editors.
Why XYFlow
XYFlow (formerly React Flow) is purpose-built for node-based UIs. It handles pan, zoom, selection, and connections — you focus on defining nodes and their behavior.
The library supports custom node types, edge styles, and interactions. It's well-documented and widely used for everything from workflow builders to visual programming environments.
Key Features
What XYFlow provides:
Custom Nodes
Any React component. Build nodes with custom UI, inputs, and behaviors.
Connections
Connect nodes visually. Drag to connect, custom edge styles, animated edges.
Interactions
Pan, zoom, select. Built-in controls with customizable behavior.
Catalyst Integration
Catalyst includes a diagrams module:
modules/diagrams/Full diagram module with persistence
app/(app)/app/diagrams/Diagram editor pages
Quick Start
Basic flow
"use client"
import { ReactFlow, Background, Controls } from "@xyflow/react"
import "@xyflow/react/dist/style.css"
const initialNodes = [
{ id: "1", position: { x: 0, y: 0 }, data: { label: "Start" } },
{ id: "2", position: { x: 0, y: 100 }, data: { label: "Process" } },
{ id: "3", position: { x: 0, y: 200 }, data: { label: "End" } },
]
const initialEdges = [
{ id: "e1-2", source: "1", target: "2" },
{ id: "e2-3", source: "2", target: "3" },
]
export function FlowDiagram() {
return (
<div style={{ width: "100%", height: 500 }}>
<ReactFlow
nodes={initialNodes}
edges={initialEdges}
fitView
>
<Background />
<Controls />
</ReactFlow>
</div>
)
}Interactive flow with state
import { useState, useCallback } from "react"
import {
ReactFlow,
addEdge,
useNodesState,
useEdgesState,
Background,
Controls,
MiniMap,
} from "@xyflow/react"
export function InteractiveFlow() {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes)
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges)
const onConnect = useCallback((params) => {
setEdges((eds) => addEdge(params, eds))
}, [setEdges])
return (
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
fitView
>
<Background />
<Controls />
<MiniMap />
</ReactFlow>
)
}Custom node type
import { Handle, Position } from "@xyflow/react"
function CustomNode({ data }) {
return (
<div className="rounded-lg border bg-background p-4 shadow-sm">
<Handle type="target" position={Position.Top} />
<div className="font-medium">{data.label}</div>
{data.description && (
<div className="text-sm text-muted-foreground">{data.description}</div>
)}
<Handle type="source" position={Position.Bottom} />
</div>
)
}
// Register in nodeTypes
const nodeTypes = { custom: CustomNode }
<ReactFlow nodeTypes={nodeTypes} ... />Built-in Components
BackgroundGrid or dot pattern background
ControlsZoom in/out, fit view, lock buttons
MiniMapOverview minimap for navigation
PanelPositioned panels for UI overlays
Tips
Import the CSS. XYFlow needs its stylesheet for proper rendering of controls and edges.
Set container dimensions. The ReactFlow component needs a sized parent — won't work without width/height.
Use hooks for state. useNodesState and useEdgesState handle immutable updates correctly.
Memoize custom nodes. Wrap custom node components in memo() to prevent unnecessary re-renders.
Learn More
For AI Agents
Key rules:
- Import from
@xyflow/react - Import
@xyflow/react/dist/style.css - Container must have explicit width and height
- Use useNodesState/useEdgesState for state management
- Check
modules/diagrams/for Catalyst patterns - Memoize custom node components