Tutorial: Implementing React Flow in Sanity Studio for Interactive and Editable Flow Diagrams
April 10, 2026
reactflowsanitynextjsportable-textdiagram

Implementing React Flow in Sanity Studio
This article explains how to implement React Flow in Sanity Studio to build interactive and editable flow diagrams. The workflow is reproducible for other developers and includes schema setup, custom input, and frontend rendering for case study pages.
Prerequisites
- A Next.js project using the App Router.
- Sanity Studio integrated under an admin route.
- The @xyflow/react package installed.
Implementation Algorithm
- Define node and edge schemas in Sanity so the graph is stored as structured data.
- Create a React Flow-based custom input component to add, drag, and connect nodes.
- Sync editor changes to architectureGraph using Sanity form patch operations.
- Render the graph in the case study frontend for desktop and mobile layouts.
- Backfill legacy case studies with architectureGraph so all documents are editable in Studio.
Snippet: Graph Schema in Sanity
src/sanity/schemaTypes/architectureGraph.ts
import {defineArrayMember, defineField, defineType} from 'sanity'
export const architectureGraphType = defineType({
name: 'architectureGraph',
title: 'Architecture Graph',
type: 'object',
fields: [
defineField({
name: 'nodes',
type: 'array',
of: [defineArrayMember({type: 'architectureGraphNode'})],
validation: (Rule) => Rule.required().min(1),
}),
defineField({
name: 'edges',
type: 'array',
of: [defineArrayMember({type: 'architectureGraphEdge'})],
}),
],
})Snippet: React Flow Custom Input in Studio
src/sanity/components/ArchitectureGraphInput.tsx
import {ReactFlow, useNodesState, useEdgesState, addEdge} from '@xyflow/react'
import {set, type ObjectInputProps} from 'sanity'
export default function ArchitectureGraphInput(props: ObjectInputProps<any>) {
const [nodes, setNodes, onNodesChange] = useNodesState([])
const [edges, setEdges, onEdgesChange] = useEdgesState([])
return (
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={(connection) =>
setEdges((current) => addEdge({...connection, type: 'smoothstep', animated: true}, current))
}
fitView
nodesDraggable
panOnDrag
/>
)
}
// Sync changes back to Sanity when nodes/edges update
// props.onChange(set({nodes, edges}))Snippet: Render Graph in Case Study
src/components/LiveArchitecture.tsx
<ReactFlow
nodes={renderedNodes}
edges={renderedEdges}
fitView
fitViewOptions={isMobile
? {padding: 0.24, minZoom: 0.74, maxZoom: 1}
: {padding: 0.16, minZoom: 0.68, maxZoom: 1}
}
nodesDraggable
panOnDrag
panOnScroll={!isMobile}
/>