Getting started
InstallationQuick startControlled and uncontrolled state
Entities
The entity modelSockets and widgetsEntity typesFrames and groupsText and commentsImages, video and models
Edges and connections
EdgesConnections
Data
EvaluationSaving and exportingUndo and redoLayout and alignmentThe flow storeGraph queriesClipboard and cloning
Interaction
Canvas and cameraSelectionKeyboardSelection toolbarContext menusDrawingDropping and pasting media
Styling
ThemingEntity stylingFonts and text renderingMinimap
API reference
KookieFlowThe ref instanceHooksUtilitiesTypes
StartEntitiesDataAPI
MarkdownOpenAIClaude

Quick start

Build a two-node graph step by step: describe the entities, give them sockets, hold them in state, and drag a wire between them.

You'll build a graph with two nodes and connect them by dragging a wire from one to the other. Your component holds the nodes and wires in React state, and the canvas reports each change you make back to that state. This page assumes you've finished Installation.

Describe two entities

Everything on the canvas is an entity: a plain object with an id, a type, a position and some data. Nodes are entities, and so are frames, comments, pictures and text.

import type { Entity } from "@kushagradhawan/kookie-flow";const initialEntities: Entity[] = [  { id: "constant", type: "constant", position: { x: 0, y: 0 }, data: { label: "Constant" } },  { id: "viewer", type: "viewer", position: { x: 320, y: 0 }, data: { label: "Viewer" } },];
  • id names the entity. Wires and change reports refer to it, so it must be unique.
  • type is any string. Eight names, such as frame, text and image, are built-in kinds of entity with behaviour of their own. Any other string, like constant here, is a node.
  • position is the node's top-left corner in world units. y grows downward, as it does on a web page.
  • data.label is the title the node shows.

The node is 240 units wide unless you set width, and it's as tall as its contents need. The entity model chapter describes every field.

Give them sockets

A socket is a point on a node that a wire attaches to. Outputs sit on the node's right edge and inputs sit on its left. Give the first node an output and the second an input:

const initialEntities: Entity[] = [  {    id: "constant",    type: "constant",    position: { x: 0, y: 0 },    data: { label: "Constant" },    outputs: [{ id: "value", name: "Value", type: "float" }],  },  {    id: "viewer",    type: "viewer",    position: { x: 320, y: 0 },    data: { label: "Viewer" },    inputs: [{ id: "value", name: "Value", type: "float" }],  },];

Each socket has an id, a name that the node prints beside it, and a type. float is one of the socket types the library defines for you. It colours the socket blue, and an input of that type draws a slider while nothing is wired into it.

A socket's id only has to be unique among that node's inputs, or among its outputs. That's why both sockets can be called value. Sockets and widgets lists the built-in types and shows how to add your own.

Hold the graph in state

useGraph keeps the entities and edges in React state and gives you the handlers that update them. Pass all five values to KookieFlow:

const { entities, edges, onEntitiesChange, onEdgesChange, onConnect } = useGraph({  initialEntities,});return (  <KookieFlow    entities={entities}    edges={edges}    onEntitiesChange={onEntitiesChange}    onEdgesChange={onEdgesChange}    onConnect={onConnect}  />);

Each handler has its own job:

  • onEntitiesChange receives moves, resizes, new entities and deletions.
  • onEdgesChange receives wires being deleted.
  • onConnect runs when you drop a wire on a socket that accepts it.

The canvas doesn't create an edge when you connect two sockets. It calls onConnect with the two ends, and useGraph adds the edge to edges. Leave onConnect out and the wire follows your pointer, then disappears when you let go.

useGraph reads initialEntities once, when the component mounts, and ignores the value on every later render. Define the array outside the component, so it's created once.

Frame the view

The canvas opens at zoom 1 with the world's origin in the top-left corner of the box, so the nodes sit against the top-left edge. Call fitView once after mount to centre them. It's a method on the instance you get by passing a ref to KookieFlow:

const flowRef = useRef<KookieFlowInstance>(null);useEffect(() => {  flowRef.current?.fitView({ padding: 80 });}, []);

Then add ref={flowRef} to the KookieFlow element. padding leaves space between the nodes and the edge of the box. fitView zooms out as far as it needs to, and it doesn't zoom in past 100% unless you pass a larger maxZoom. Canvas and camera covers the other view methods.

Here is the whole file, running:

Arrow keys move between nodes. Press Enter to reach the focused node's controls, and Escape to come back here.

'use client';import { useEffect, useRef } from 'react';import {  KookieFlow,  useGraph,  type Entity,  type KookieFlowInstance,} from '@kushagradhawan/kookie-flow';// Two nodes: one with a float output, one with a float input.const initialEntities: Entity[] = [  {    id: 'constant',    type: 'constant',    position: { x: 0, y: 0 },    data: { label: 'Constant' },    outputs: [{ id: 'value', name: 'Value', type: 'float' }],  },  {    id: 'viewer',    type: 'viewer',    position: { x: 320, y: 0 },    data: { label: 'Viewer' },    inputs: [{ id: 'value', name: 'Value', type: 'float' }],  },];export default function QuickStartExample() {  const { entities, edges, onEntitiesChange, onEdgesChange, onConnect } = useGraph({    initialEntities,  });  // Frame both nodes once, whatever width the box turns out to be.  const flowRef = useRef<KookieFlowInstance>(null);  useEffect(() => {    flowRef.current?.fitView({ padding: 80 });  }, []);  return (    <div style={{ width: '100%', height: 360 }}>      <KookieFlow        ref={flowRef}        entities={entities}        edges={edges}        onEntitiesChange={onEntitiesChange}        onEdgesChange={onEdgesChange}        onConnect={onConnect}      />    </div>  );}

Try the canvas

Click the canvas first. It only answers keys while it has focus, so a page that embeds it keeps its own shortcuts.

  • Connect the sockets. Press on either Value socket and drag to the other one. When you let go, the wire stays and the slider on the Viewer's input goes away.
  • Move a node. Drag it by its body.
  • Select several. Drag across empty canvas to draw a selection box. Hold Cmd or Ctrl to add to the current selection, or to click a node out of it.
  • Delete. Click a node or a wire, then press Delete or Backspace. Deleting a node also deletes its wires.
  • Pan. Hold Space and drag, or drag with the middle mouse button.
  • Zoom. Pinch on a trackpad, or hold Cmd or Ctrl and scroll. In your own app a plain scroll zooms too, but on this page it scrolls the page.
  • Clear the selection. Press Escape.

Where to go next

Each step on this page has a chapter of its own:

  • Controlled and uncontrolled state explains what the canvas reports, and how to keep the graph in your own store instead of useGraph.
  • The entity model describes every field an entity can carry.
  • Sockets and widgets covers socket types and the controls on inputs.
  • Connections shows how to decide which sockets may connect.
  • Canvas and camera covers zoom limits, the grid and the view methods.
  • Keyboard lists every key the canvas answers.
Getting started
  • Installation
  • Quick start
  • Controlled and uncontrolled state
Entities
  • The entity model
  • Sockets and widgets
  • Entity types
  • Frames and groups
  • Text and comments
  • Images, video and models
Edges and connections
  • Edges
  • Connections
Data
  • Evaluation
  • Saving and exporting
  • Undo and redo
  • Layout and alignment
  • The flow store
  • Graph queries
  • Clipboard and cloning
Interaction
  • Canvas and camera
  • Selection
  • Keyboard
  • Selection toolbar
  • Context menus
  • Drawing
  • Dropping and pasting media
Styling
  • Theming
  • Entity styling
  • Fonts and text rendering
  • Minimap
API reference
  • KookieFlow
  • The ref instance
  • Hooks
  • Utilities
  • Types
Reference
  • Live demo
  • llms.txt
  • GitHub
MIT licensed. © 2026 Kushagra Dhawan.
On this page
  • Describe two entities
  • Give them sockets
  • Hold the graph in state
  • Frame the view
  • Try the canvas
  • Where to go next