Skip to main content
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.

High-level architecture

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

Module structure

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

Component hierarchy

When you mount mountFlowDropApp(), this is the component tree:
mountWorkflowEditor() mounts just the canvas — no navbar, no sidebar. Each mount produces one such tree backed by its own instance; node/field registries and settings are shared across all trees on the page.

Stores

FlowDrop uses Svelte 5 runes for state management. Each mount creates a per-instance FlowDropInstance container that holds these stores:

Instance model

Every mount creates an isolated FlowDropInstance container holding the stores above (workflow, history, playground, interrupts, categories, port coordinates, and pipeline-panel state), resolved through Svelte context. Multiple editors can therefore coexist on one page without sharing state. See the multiple instances guide for details.

Services

Services handle communication and side effects:

Data flow

Here’s what happens when a user makes a change: When the user saves:

Registry system

FlowDrop has two registries for extending the editor:

Node component registry

Register custom Svelte components for new node types against the instance’s fd.nodes registry:

Field component registry

Register custom form fields for config schemas against fd.fields:
Both registries are instance-scoped — seeded with builtins in the instance constructor and resolved via getInstance(). You can register after mounting.
BaseRegistry tracks a version counter that invalidates dependent $derived reads, so registrations made after mount still take effect.

Next steps