Overview

FlowKit is a powerful visual workflow builder and execution engine for the browser. Create, edit, test, and run automation workflows through an intuitive drag-and-drop interface with real-time execution feedback.

Visual Builder
Drag-and-drop interface with 70+ node types. Connect nodes visually, configure properties in side panels, and organize with grouping.
Execution Engine
Run complete workflows or test individual nodes. Real-time state visualization, execution logs, and variable inspection.
Extensible
Register custom node types with your own icons, fields, and logic. Create custom executors for specialized business requirements.
Portable
Export workflows as JSON for storage/sharing, Mermaid diagrams for documentation, or PNG images for presentations.

Key Features

  • 70+ built-in node types - Triggers, actions, conditions, loops, HTTP, email, Slack, AWS, and more
  • 15 specialized executors - Each node type has a dedicated executor with validation and configuration
  • Real-time execution - Watch workflows run with visual state indicators (pending, running, success, error)
  • Variable interpolation - Use {{lastResult.data}} syntax to pass data between nodes
  • Full editing suite - Undo/redo (50 levels), copy/paste, multi-select, duplicate, group nodes
  • Navigation aids - Minimap, zoom controls, fit-to-view, pan with space+drag
  • Multiple exports - JSON (for import), Mermaid (for docs), PNG image (for sharing)
  • Customizable canvas - Dot/grid/line patterns, light/dark themes, snap-to-grid, animated edges
  • Condition branch colors - Green for true path, red for false path on condition nodes
Browser Support

FlowKit works in all modern browsers (Chrome, Firefox, Safari, Edge). No server required - runs entirely in the browser.

Installation

NPM

npm install flowkit

CDN

<script src="https://unpkg.com/flowkit/dist/flowkit.umd.js"></script>

ES Module

import { WorkflowBuilder, WorkflowExecutor } from 'flowkit';

Quick Start

import { WorkflowBuilder } from 'flowkit';

// Initialize builder
const container = document.getElementById('app');
const builder = new WorkflowBuilder(container, {
  theme: 'light',
  background: 'dots',
  minimap: true
});

// Add nodes
builder.addNode('trigger', 100, 100);
builder.addNode('action', 300, 100);
builder.addNode('end', 500, 100);

// Connect nodes
builder.connect('1', '2');
builder.connect('2', '3');

// Execute workflow
await builder.runWorkflow();

WorkflowBuilder

The main class for creating and managing visual workflows.

Constructor Options

Option Type Default Description
theme string light Color theme: 'light' or 'dark'
mode string edit Mode: 'edit' (full editing) or 'view' (read-only)
nodes array ['trigger', 'action', ...] Array of node type names to enable
background string dots Canvas pattern: 'none', 'dots', 'lines', 'grid'
edgeType string bezier Connection style: 'bezier', 'straight', 'step'
minimap boolean true Show minimap navigation panel
snapToGrid boolean false Snap nodes to grid when dragging
gridSize number 20 Grid size in pixels for snapping
animatedEdges boolean false Animate edges with flowing dots
showArrows boolean true Show arrow markers on connection ends
customNodes object {} Custom node type definitions
onSave function null Callback when workflow is saved
onChange function null Callback fired on any workflow change

Example with All Options

const builder = new WorkflowBuilder('#app', {
  theme: 'dark',
  mode: 'edit',
  nodes: ['trigger', 'action', 'condition', 'email', 'http'],
  background: 'grid',
  edgeType: 'bezier',
  minimap: true,
  snapToGrid: true,
  gridSize: 20,
  animatedEdges: true,
  showArrows: true,
  customNodes: {
    myNode: {
      label: 'My Custom Node',
      icon: '⭐',
      category: 'custom',
      inputs: 1,
      outputs: 1,
      fields: []
    }
  },
  onSave: (data) => console.log('Saved:', data),
  onChange: (data) => console.log('Changed:', data)
});

Methods

MethodDescription
addNode(type, x, y)Add a node at position. Returns node ID.
removeNode(nodeId)Remove a node by ID.
getNode(nodeId)Get node data by ID.
getNodes()Get all nodes as array.
connect(fromId, toId)Create connection between two nodes.
registerNode(name, def)Register a custom node type.
MethodDescription
undo()Undo last action
redo()Redo undone action
clear()Clear entire workflow
copySelected()Copy selected nodes
paste()Paste copied nodes
deleteSelected()Delete selected nodes
zoomIn() / zoomOut()Change zoom level
fitView()Fit all nodes in view
groupSelected()Group selected nodes together
ungroupSelected()Ungroup selected nodes
setTheme(theme)Set 'light' or 'dark' theme
setMode(mode)Set 'edit' or 'view' mode
toggleMinimap()Show/hide minimap panel
toggleSnap()Toggle snap to grid
MethodDescription
runWorkflow()Execute entire workflow
runFromNode(nodeId)Run from specific node
runSingleNode(nodeId)Test single node
pauseWorkflow()Pause execution
stopWorkflow()Stop execution
resetWorkflow()Reset execution state
getExecutionState()Export execution state for persistence
setExecutionState(state)Restore execution state
getExecutionLog()Get execution history array
getExecutionContext()Get data passed between nodes
MethodDescription
export()Returns workflow data object
import(data)Import workflow from data
exportWorkflow()Download as JSON file
exportAsImage()Export as PNG image
validate()Validate workflow structure
MethodDescription
setNodeColor(nodeId, color)Set color of a specific node
setConnectionColor(from, to, color)Set color of a specific connection
setDefaultConnectionColor(color)Set default color for all connections
setConditionColors(true, false)Set colors for condition branches

Node Types

70+ built-in node types organized into categories. Each node can be dragged from the sidebar onto the canvas.

Core Nodes

Trigger
trigger
Action
action
Condition
condition
Loop
loop
Delay
delay
Transform
transform
Filter
filter
End
end

Integration Nodes

HTTP
http
API
api
Webhook
webhook
Database
database
Email
email
Slack
slack
AWS
aws
Docker
docker

Condition Node (Special)

Condition nodes have two outputs with automatic color coding:

  • Output 1 (True/Yes): Green - followed when condition evaluates to true
  • Output 2 (False/No): Red - followed when condition evaluates to false

The output dots and connection lines are automatically colored to visually indicate the branch direction.

Condition Expression
Use JavaScript expressions in condition nodes:
{{lastResult.data.status}} == 'active'
{{lastResult.data.count}} > 10
{{lastResult.data.items}}.length > 0

Executors

Each node type is handled by a specialized executor with specific configuration options. Executors process nodes during workflow execution.

ExecutorNode TypesDescription
TriggerExecutortrigger, start, schedule, webhookWorkflow entry points. Sets initial variables and context.
ActionExecutoraction, process, taskGeneral actions: HTTP calls, code execution, logging, set variables.
ConditionExecutorcondition, if, decision, switchBranching logic. Evaluates expressions and routes to output_1 (true) or output_2 (false).
LoopExecutorloop, foreach, whileIterate over arrays. Provides {{item}} and {{index}} variables.
TransformExecutortransform, map, merge, splitData transformation: map, filter, reduce, merge objects, split strings.
FilterExecutorfilterFilter arrays based on conditions.
DelayExecutordelay, wait, sleepPause execution for specified duration.
HttpExecutorhttp, api, requestMake HTTP/HTTPS requests. Supports all methods, headers, body, auth.
EmailExecutoremail, sendmailSend emails with to, subject, body, attachments.
DatabaseExecutordatabase, sql, queryExecute database queries (simulated in browser).
SlackExecutorslack, notificationSend Slack messages to channels.
AwsExecutoraws, s3, lambdaAWS service calls (S3, Lambda, SQS).
DockerExecutordocker, containerDocker operations (simulated).
CodeExecutorcode, script, functionExecute JavaScript code with access to context.
EndExecutorend, stop, terminateWorkflow termination. Returns final result.

Executor Result Structure

Every executor returns a consistent result object:

{
  success: true,              // Whether execution succeeded
  data: { ... },              // Result data (varies by executor)
  output: 'output_1',         // Which output to follow (for conditions)
  error: null,                // Error message if failed
  nextNodes: ['2']            // IDs of next nodes to execute
}

Custom Executor

Register a custom executor for your node type:

// Register custom executor
builder.registerExecutor('myNode', async (node, context) => {
  const config = node.data;
  
  // Access previous results
  const lastResult = context.variables.lastResult;
  
  // Do work...
  const result = await myCustomLogic(config.option);
  
  return {
    success: true,
    data: result
  };
});

Keyboard Shortcuts

Undo
CtrlZ
Redo
CtrlY
Delete
Delete
Copy
CtrlC
Paste
CtrlV
Duplicate
CtrlD
Select All
CtrlA
Save
CtrlS
Group/Ungroup
CtrlG
Pan Canvas
SpaceDrag
Multi-Select
ShiftClick
Deselect
Escape

Variable Interpolation

Use {{variable}} syntax to insert dynamic values into any field.

VariableDescription
{{lastResult}}Full result of previous node
{{lastResult.data}}Data from previous node
{{lastResult.data.field}}Specific field from result
{{node_1}}Result of node with ID 1
{{item}}Current item in loop
{{index}}Current index in loop

Examples

// In HTTP URL
"https://api.example.com/users/{{lastResult.data.id}}"

// In condition
"{{lastResult.data.status}} == 'active'"

// In email body
"Hello {{lastResult.data.name}}, your order is ready."

Custom Nodes

Register a Custom Node

builder.registerNode('myNode', {
  label: 'My Custom Node',
  icon: '<svg>...</svg>',
  color: '#FF5733',
  inputs: 1,
  outputs: 2,
  fields: [
    { name: 'option', label: 'Option', type: 'select',
      options: [
        { value: 'a', label: 'Option A' },
        { value: 'b', label: 'Option B' }
      ]
    }
  ]
});

Field Types

textSingle line text input
textareaMulti-line text
numberNumeric input
selectDropdown with options
checkboxBoolean toggle
jsonJSON editor
codeCode editor

Connection Styling

Customize the appearance of connections and nodes programmatically.

Default Connection Color

Set the default color for all connections:

// Set default connection color (teal)
builder.setDefaultConnectionColor('#02514a');

// Set to custom color
builder.setDefaultConnectionColor('#FF5733');

Individual Connection Color

Change color of a specific connection:

// Set connection color between node 1 and node 2
builder.setConnectionColor(1, 2, '#8B5CF6');

// With specific output/input classes
builder.setConnectionColor(1, 2, '#EC4899', 'output_1', 'input_1');

Condition Node Colors

Condition nodes (condition, if, decision) have two outputs with automatic coloring:

  • Output 1 (True/Success): Green (#22C55E) by default
  • Output 2 (False/Error): Red (#EF4444) by default

Customize condition branch colors:

// Set custom colors for condition branches
builder.setConditionColors('#10B981', '#F97316');
// First param: true/success color (output_1)
// Second param: false/error color (output_2)

Node Color

Change the color of individual nodes:

// Set node color
builder.setNodeColor(nodeId, '#FF5733');
Condition Node Behavior
When a condition evaluates to true, execution follows the green output (output_1). When it evaluates to false, execution follows the red output (output_2). The output dots and connection lines are automatically colored to indicate the branch direction.

Events

Listen to workflow events for integration with your application.

Using Callbacks

const builder = new WorkflowBuilder('#app', {
  onChange: (data) => {
    console.log('Workflow changed:', data);
    // Auto-save, validation, etc.
  },
  onSave: (data) => {
    console.log('Workflow saved:', data);
    // Send to server, show notification, etc.
  }
});

Available Events

EventDescriptionData
onChangeFired on any workflow changeFull workflow data object
onSaveFired when Ctrl+S or Save clickedFull workflow data object
nodeCreatedWhen a node is addedNode ID and type
nodeRemovedWhen a node is deletedNode ID
connectionCreatedWhen nodes are connectedSource and target IDs

Drawflow Events

Access underlying Drawflow events for advanced control:

// Access Drawflow instance
builder.drawflow.on('nodeCreated', (id) => {
  console.log('Node created:', id);
});

builder.drawflow.on('connectionCreated', ({ output_id, input_id }) => {
  console.log('Connected:', output_id, '->', input_id);
});

builder.drawflow.on('nodeMoved', (id) => {
  console.log('Node moved:', id);
});

Examples

Click Examples dropdown in VizFlow to load any of these pre-built workflows.

1. API Request Test

What it does: Makes one API call and transforms the response.

Use case: Quick API endpoint testing, validating response format.

Flow: Trigger → HTTP → Transform → End

StepNodeConfiguration
1TriggerClick "Run" to start
2HTTPurl: https://jsonplaceholder.typicode.com/todos/1
3Transformreturn { title: data.title, completed: data.completed };
// Expected output:
{ "title": "delectus aut autem", "completed": false }

2. Data Pipeline

What it does: Fetches users, filters invalid entries, transforms to clean format.

Use case: Clean contact lists from CRM API for mailing list.

Flow: Trigger → HTTP → Filter → Transform → End

StepNodeConfiguration
1TriggerManual start
2HTTPurl: https://jsonplaceholder.typicode.com/users
3Filterreturn item.address && item.address.city;
4Transformreturn data.map(u => ({ name: u.name, email: u.email, city: u.address.city }));

3. Condition Flow

What it does: Routes workflow differently based on API response data.

Use case: Process tickets by status, route orders by type.

Flow: Trigger → HTTP → Condition → (True: Action A | False: Action B) → End

StepNodeConfiguration
1TriggerManual start
2HTTPurl: https://jsonplaceholder.typicode.com/todos/1
3ConditionconditionType: javascript
js_condition: return ctx.lastResult?.data?.completed === true;
4aAction (True)output_1 → Task completed handler
4bAction (False)output_2 → Task incomplete handler

4. Loop Example

What it does: Iterates over array, processing each item individually.

Use case: Process batch orders, send individual emails to list.

Flow: Trigger → Loop → Transform → (back to Loop) → End

StepNodeConfiguration
1Triggerdata: { items: [1, 2, 3, 4, 5] }
2Loopsource: {{lastResult.data.items}}
3Transformreturn { value: ctx.item * 2, original: ctx.item };
// Inside loop, access:
ctx.item   // Current item (e.g., 1, 2, 3...)
ctx.index  // Current index (0, 1, 2...)

5. Notification Flow

What it does: Sends notifications via Email AND Slack simultaneously.

Use case: Alert multiple channels on new order, system events.

Flow: Trigger → HTTP → (Email + Slack) → End

StepNodeConfiguration
1TriggerManual or webhook
2HTTPFetch data to notify about
3aEmailto: user@example.com
subject: New: {{lastResult.data.title}}
3bSlackchannel: #notifications
message: {{lastResult.data.title}}

6. Error Handling

What it does: Demonstrates graceful handling of API failures.

Use case: Alert when services are down, retry logic.

Flow: Trigger → HTTP → (Success: Handler | Error: Alert) → End

StepNodeConfiguration
1TriggerManual start
2HTTPoutput_1: Success (2xx)
output_2: Error (4xx, 5xx, timeout)
3aSuccessProcess successful response
3bErrorSend alert, log error
// Error result structure:
{ "error": "500 Internal Server Error", "ok": false, "status": 500 }

7. Full API Workflow

What it does: Complete API integration with auth, validation, filtering.

Use case: Build user dashboard with filtered content.

Flow: Trigger → HTTP → Condition → HTTP → Transform → Filter → End

StepNodeConfiguration
1Triggerdata: { userId: 1 }
2HTTPurl: /users/{{data.userId}}
headers: {"Authorization": "Bearer token"}
3Conditionfield: company.name, operator: not_empty
4HTTPurl: /posts?userId={{lastResult.data.id}}
5Filterreturn item.title.length > 20;

8. Data Enrichment

What it does: For each user, fetch posts AND todos, merge together.

Use case: Build complete customer profiles from microservices.

Flow: Trigger → HTTP → Loop → HTTP → Transform → End

StepNodeConfiguration
1HTTPFetch list of users
2Loopsource: {{lastResult.data}}
3HTTPurl: /posts?userId={{item.id}}
4Transformreturn { user: ctx.item, posts: data };

9. Multi-Channel Alert

What it does: Monitors API health, sends alerts via Email, Slack, PagerDuty.

Use case: Production monitoring, uptime checks.

Flow: Schedule → HTTP → Condition → (OK: Log | Down: Alert → PagerDuty) → End

StepNodeConfiguration
1SchedulecronExpression: */5 * * * * (every 5 min)
2HTTPurl: /health
timeout_seconds: 5
3Conditionfield: status, operator: equals, value: healthy
4Alertto: ops-team@example.com
subject: API Down!

10. ETL Pipeline

What it does: Extract-Transform-Load: fetch data, process, save to database.

Use case: Nightly data sync between systems.

Flow: Schedule → HTTP → Filter → Transform → Loop → Database → End

StepNodeConfiguration
1SchedulecronExpression: 0 2 * * * (daily 2 AM)
2HTTPFetch source data
3Filterreturn item.userId <= 2;
4Transformreturn data.map(p => ({ ...p, title: p.title.toUpperCase() }));
5LoopProcess each item
6Databaseoperation: insert, table: posts, data: {{item}}

Context Variables

These variables are available in all node configurations:

VariableDescriptionExample
ctxFull execution contextctx.lastResult
ctx.lastResultPrevious node resultctx.lastResult.data
ctx.node_NSpecific node by IDctx.node_2.data
dataShortcut for lastResult.datadata.map(...)
ctx.itemCurrent loop itemctx.item.id
ctx.indexCurrent loop index (0-based)ctx.index + 1

Interpolation Syntax

// Use {{}} in string fields:
url: 'https://api.example.com/users/{{data.userId}}'
message: 'Processing item {{item.name}} at index {{index}}'

// Use direct JS in code fields:
return data.filter(x => x.active);