[]previous and next page

How it fits together

The five layers of CanvasFlow, what each one owns, and which one you reach for when you want to change something.

CanvasFlow is built in layers. Each layer only knows about the ones below it, which is why you can swap the top ones out (your own UI, React Native instead of the web) without touching the rest.

text
┌──────────────────────────────────────────────────────────┐
│  UI          toolbar, style panel, menus, palette         │  canvasflow/ui · your own
├──────────────────────────────────────────────────────────┤
│  Bindings    React, Vue, Solid, Svelte, Angular, …         │  canvasflow/react · vue · …
├──────────────────────────────────────────────────────────┤
│  Host        SVG renderer, input, text editing, clipboard │  canvasflow/dom · react-native
├──────────────────────────────────────────────────────────┤
│  Editor      state, camera, selection, tools, actions     │
├──────────────────────────────────────────────────────────┤
│  Shapes      geometry + render nodes per shape type       │  canvasflow (headless)
├──────────────────────────────────────────────────────────┤
│  Store       immutable records, diffs, history, sync      │
└──────────────────────────────────────────────────────────┘

The store holds the document#

Everything on a board is a record: a plain, immutable object with an id and a typeName. Shapes, pages, bindings between arrows and shapes, assets like images, and the document itself are all records. The store keeps them and reports every change as a diff: what was added, updated and removed.

History (undo and redo), autosave and collaboration all work from those diffs. That's why they work together: a remote edit, an undo and a load from storage are the same kind of event. Read more in Records and the store.

Shapes describe themselves#

Each shape type has a ShapeUtil: a small class that says what the shape's default props are, what its outline is (its geometry), and how it draws (a tree of render nodes). Render nodes are renderer-agnostic: the web host turns them into SVG elements, React Native into react-native-svg components, and the exporter into an SVG string.

The geometry is the source of truth for interaction. Hover, selection, the marquee, the eraser, snapping and arrow bindings all ask the geometry, never the pixels. See Shapes.

The editor is the brain#

The editor owns the instance state (the camera, the current page, the selection, the active tool, the styles for the next shape) and exposes every operation as a method: create, update, align, group, zoom, copy, export. It also runs the tools, which are small state machines that turn pointer and keyboard events into edits (Tools), and the actions, one declaration per command that feeds shortcuts, menus and the palette (Actions and shortcuts).

The editor never touches window or the DOM. It runs the same in a browser, a worker, Node or React Native.

The host connects it to a screen#

canvasflow/dom mounts an editor into an element. It renders shapes as SVG (one <g> per shape, only changed shapes re-render, off-screen shapes are culled), translates pointer, wheel, touch, pen and keyboard input into editor events, edits text in place, and handles the clipboard and dropped files.

On mobile, canvasflow/react-native plays the same role with react-native-svg.

Bindings connect it to your framework#

A binding (canvasflow/react, vue, solid, svelte, angular, preact, shadow) is a thin layer over the host and the UI. It mounts them in your framework's lifecycle, and hands the editor's state to your framework in its own reactivity: hooks, refs, signals or stores. There is nothing in a binding that you could not write yourself with createCanvasFlow and editor.subscribe. See Choose your framework.

The UI is optional#

canvasflow/ui is the default interface, written without a framework so it works anywhere. Every piece can be turned off, and you can add your own components into its slots. Or skip it entirely and build your own: the editor tells you everything you need through events and state. See Customizing the UI and Building your own UI.

Which layer do I change?#

You want to… Reach for
Add a new kind of shape A ShapeUtil or defineShape (Custom shapes)
Change how a gesture works A tool (Custom tools)
Add a command with a shortcut An action (Actions and shortcuts)
Save somewhere else A storage adapter (Saving and storage)
Sync between people A transport (Collaboration)
Change the look A theme or CSS (Styles and themes)
Replace the toolbar Your own UI on the editor (Building your own UI)