---
name: svelte-flow
description: Build node-based editors, interactive diagrams, and flow visualizations using Svelte Flow. Use when creating workflow editors, data flow diagrams, organizational charts, mindmaps, process visualizations, DAG editors, or any interactive node-graph UI. Supports custom nodes/edges, layouts (dagre, hierarchical), animations, and advanced features like proximity connect, floating edges, and contextual zoom.
keywords: [svelte-flow, visualization, nodes, graph-editor, diagrams, interactive-ui]
---
# Svelte Flow
Expert guide for building node-based UIs with Svelte Flow (@xyflow/svelte).
## Installation
```bash
npm install @xyflow/svelte
```
## Core Setup
```svelte
```
## Key Concepts
### Nodes
Each node requires:
- `id`: Unique identifier
- `position`: `{ x: number, y: number }`
- `data`: Object with custom properties (typically includes `label`)
- Optional: `type`, `style`, `hidden`, `width`, `height`, `sourcePosition`, `targetPosition`
```typescript
const node = {
id: '1',
type: 'custom',
position: { x: 100, y: 100 },
data: { label: 'My Node', color: '#ff0000' },
style: 'background: #f0f0f0',
width: 150,
height: 100
};
```
### Edges
Each edge requires:
- `id`: Unique identifier
- `source`: Source node ID
- `target`: Target node ID
- Optional: `type`, `label`, `animated`, `markerEnd`, `markerStart`, `style`, `hidden`
```typescript
const edge = {
id: 'e1-2',
source: '1',
target: '2',
type: 'smoothstep',
label: 'connects to',
animated: true,
markerEnd: { type: MarkerType.ArrowClosed }
};
```
### Built-in Types
**Edge Types:**
- `default`: Straight line
- `smoothstep`: Smooth 90-degree turns
- `step`: Hard 90-degree turns
- `straight`: Alias for default
- `bezier`: Curved bezier line
**Node Types:**
- `default`: Basic rectangle node
- `input`: Node with only source handles
- `output`: Node with only target handles
## Custom Nodes
```svelte
```
Register custom nodes:
```svelte
```
## Custom Edges
```svelte
{#if label}
{label}
{/if}
```
Path helpers available:
- `getStraightPath()`
- `getBezierPath()`
- `getSmoothStepPath()`
Register custom edges:
```svelte
```
## Updating State
**Critical:** Nodes and edges are immutable. Create new objects to trigger updates.
```svelte
```
## Event Handling
Common event handlers:
```svelte
console.log('node clicked', event.targetNode)}
onnodedrag={(event) => console.log('node dragging', event.targetNode)}
onnodedragstop={(event) => console.log('drag ended', event.targetNode)}
onedgeclick={(event) => console.log('edge clicked', event.edge)}
onconnect={(params) => {
edges = [...edges, { id: `e${params.source}-${params.target}`, ...params }];
}}
/>
```
Available events:
- `onnodeclick`, `onnodedoubleclick`
- `onnodedrag`, `onnodedragstart`, `onnodedragstop`
- `onedgeclick`, `onedgedoubleclick`
- `onconnect`, `onconnectstart`, `onconnectend`
- `onbeforedelete` (async, can prevent deletion)
- `oninit`, `onmove`, `onmovestart`, `onmoveend`
## Layout Algorithms
### Dagre (Hierarchical)
```typescript
import dagre from '@dagrejs/dagre';
import { Position } from '@xyflow/svelte';
function getLayoutedElements(nodes: Node[], edges: Edge[], direction = 'TB') {
const dagreGraph = new dagre.graphlib.Graph();
dagreGraph.setDefaultEdgeLabel(() => ({}));
const isHorizontal = direction === 'LR';
dagreGraph.setGraph({ rankdir: direction });
const nodeWidth = 172;
const nodeHeight = 36;
nodes.forEach((node) => {
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
});
edges.forEach((edge) => {
dagreGraph.setEdge(edge.source, edge.target);
});
dagre.layout(dagreGraph);
const layoutedNodes = nodes.map((node) => {
const nodeWithPosition = dagreGraph.node(node.id);
return {
...node,
targetPosition: isHorizontal ? Position.Left : Position.Top,
sourcePosition: isHorizontal ? Position.Right : Position.Bottom,
position: {
x: nodeWithPosition.x - nodeWidth / 2,
y: nodeWithPosition.y - nodeHeight / 2,
},
};
});
return { nodes: layoutedNodes, edges };
}
```
## Advanced Features
### Floating Edges
Edges that dynamically connect to the closest point on node boundaries:
```svelte
```
Register with `ConnectionMode.Loose`:
```svelte
```
### Proximity Connect
Auto-connect nodes when dragged close together:
```svelte
```
### Edge Reconnection
Allow users to drag edge endpoints to different nodes:
```svelte
{#if !reconnecting}
{/if}
{#if selected}
{/if}
```
### Delete Node and Reconnect Edges
```svelte
```
## Components
### Controls
```svelte
```
### MiniMap
```svelte
```
### Background
```svelte
```
Variants: `Dots`, `Lines`, `Cross`
### Panel (Custom Controls)
```svelte
```
Positions: `top-left`, `top-center`, `top-right`, `bottom-left`, `bottom-center`, `bottom-right`
## Utility Functions
```typescript
import {
getConnectedEdges,
getIncomers,
getOutgoers,
addEdge,
applyEdgeChanges,
applyNodeChanges
} from '@xyflow/svelte';
// Get edges connected to nodes
const connectedEdges = getConnectedEdges(nodes, edges);
// Get nodes that connect TO a node
const incomers = getIncomers(targetNode, nodes, edges);
// Get nodes that a node connects TO
const outgoers = getOutgoers(sourceNode, nodes, edges);
// Add edge with validation
edges = addEdge(connection, edges);
```
## Store Management (Alternative)
For centralized state:
```javascript
// store.svelte.js
let nodes = $state.raw([...]);
let edges = $state.raw([...]);
export const getNodes = () => nodes;
export const getEdges = () => edges;
export const setNodes = (newNodes) => nodes = newNodes;
export const setEdges = (newEdges) => edges = newEdges;
```
```svelte
```
## Export to Image
```svelte
```
## Performance Tips
- Use `$state.raw` for nodes and edges (prevents deep reactivity)
- For large graphs (1000+ nodes), set `elevateNodesOnSelect={false}` and `elevateEdgesOnSelect={false}`
- Use `minZoom` and `maxZoom` to limit zoom levels
- Consider virtualization for extremely large graphs
## Common Props
```svelte
```