Skip to content

Architecture Overview

This page explains how FlowDrop is structured internally, so you can make informed decisions about what to import, how to integrate, and where to extend.

FlowDrop is a frontend library that communicates with your backend via REST.

Browser

REST API

Your Backend

Nodes · Workflows · Execution · Storage

FlowDrop Editor

UI Components

Navbar · Canvas · Config Panel

Stores

workflow · history · settings

Services

API client · drafts · toasts

FlowDrop is tree-shakable. Each sub-module has different dependencies and bundle cost:

ModuleWhat it providesHeavy deps
@flowdrop/flowdrop/coreTypes, utilities, auth providers, config helpersNone
@flowdrop/flowdrop/editorWorkflowEditor, mount functions, node components@xyflow/svelte
@flowdrop/flowdrop/formSchemaForm, field componentsNone
@flowdrop/flowdrop/form/codeCode & template editorsCodeMirror (~300KB)
@flowdrop/flowdrop/form/markdownMarkdown editorCodeMirror
@flowdrop/flowdrop/displayMarkdownDisplaymarked
@flowdrop/flowdrop/playgroundPlayground, chat, interruptsEditor + Form
@flowdrop/flowdrop/settingsSettings panel, theme toggleForm
@flowdrop/flowdrop/stylesCSS design tokensNone
@flowdrop/flowdropFull bundle (everything)All of the above

Dependency chain:

core

(types only, zero UI)

form

(JSON Schema forms)

editor

(@xyflow canvas + forms)

playground

(editor + chat + interrupts)

Import from the most specific module possible to minimize bundle size.

When you mount mountFlowDropApp(), this is the component tree:

  • DirectoryApp
    • DirectoryNavbar
      • Logo
      • WorkflowName (editable)
      • Save / Export buttons
      • Custom NavbarActions
      • ThemeToggle / Settings
    • DirectoryNodeSidebar
      • Search
      • DirectoryCategoryGroups
        • NodeCards (draggable)
    • DirectoryWorkflowEditor (@xyflow/svelte canvas)
      • DirectoryNodes (WorkflowNode, SimpleNode, GatewayNode, etc.)
        • Ports (input/output handles)
      • Edges (styled by category)
      • ConnectionLine
    • DirectoryConfigPanel (right side, on node click)
      • NodeHeader (name, type, icon)
      • DirectorySchemaForm (generated from configSchema)
        • FormFields (text, select, code, template, etc.)
    • ToastContainer

mountWorkflowEditor() mounts just the canvas — no navbar, no sidebar.

FlowDrop uses Svelte 5 runes for state management. Stores are module-level singletons:

StorePurposeKey state
workflowStoreCentral workflow statenodes, edges, metadata, isDirty
historyStoreUndo/redopast states, future states, canUndo/canRedo
settingsStoreUser preferencestheme, editor behavior, UI config
playgroundStorePlayground sessionssessions, messages, isExecuting
interruptStoreHuman-in-the-looppending/resolved interrupts
categoriesStoreNode categoriescategory definitions, colors
portCoordinateStoreHandle positionsport coordinates for edge rendering

Services handle communication and side effects:

ServicePurpose
API clientHTTP requests to your backend (nodes, workflows, execution)
Draft storageAuto-save to localStorage
Toast serviceSuccess/error/loading notifications
Dynamic schemaFetch config schemas from API at runtime
Playground serviceManage sessions, poll for messages
Interrupt serviceSubmit interrupt resolutions
History serviceTrack and replay state changes
Settings serviceLoad/save preferences (localStorage + API)

Here’s what happens when a user makes a change:

User action

(drag node, edit config, draw edge)

Component event handler

workflowStore update

(state mutation)

historyStore

records snapshot

(for undo)

isDirty

flag set to true

UI re-renders

(Svelte reactivity)

onWorkflowChange

(workflow, changeType)

---

your callback — analytics, validation, etc.

onDirtyStateChange

(true)

---

your callback — update save button, etc.

When the user saves:

return false

Success

Failure

User clicks Save

onBeforeSave(workflow)

Cancel

API client: PUT /workflows/{id}

isDirty = false, draft cleared

---

onAfterSave(workflow)

Toast notification

---

onSaveError(error, workflow)

onApiError(error, 'save')

FlowDrop has two registries for extending the editor:

Register custom Svelte components for new node types:

import { registerCustomNode } from '@flowdrop/flowdrop/editor';
registerCustomNode('my-custom-node', MyNodeComponent);

Register custom form fields for config schemas:

import { registerFieldComponent } from '@flowdrop/flowdrop/form';
registerFieldComponent(matcher, MyFieldComponent, { priority: 10 });

Both registries are singletons that persist for the page lifetime. Register before or after mounting.