A production-grade, frontend-only visual workflow automation builder. Built with React 18 · TypeScript 5 · Zustand · React Flow · TailwindCSS
The screenshot above shows a live workflow with three connected nodes — Trigger → Send Email → Delay — and the Trigger node selected in the Configuration panel on the right. The execution log at the bottom is idle, waiting to run.
npm install
npm run dev # → http://localhost:5173
npm run build # production build
npm run test:run # run all unit tests onceNode Library (left panel)
│
│ Drag any node card onto the canvas
▼
Canvas (center panel)
│
│ Drop it wherever you like — nodes snap to a 16px grid
▼
Node appears on canvas
Step-by-step:
- Drag a Trigger node from the left sidebar onto the canvas. Every workflow must start with at least one Trigger — it is the entry point.
- Drag more nodes (Send Email, Delay, Condition, Logger) and arrange them below the Trigger.
- Connect nodes by hovering over the bottom handle (circle) of a node until it turns blue, then dragging to the top handle of the next node. A directional edge is drawn.
- Move nodes freely by clicking and dragging them around the canvas.
- Delete a node by hovering over it and clicking the
×button that appears in the top-right corner of the card.
Click any node on canvas
│
▼
Configuration Panel opens (right panel)
│ ┌─────────────────────────────┐
│ │ Node Label [Trigger ] │
│ │ Event Name * [user.signup ] │ ← required field (red *)
│ │ Description [ ] │
│ │ │
│ │ ID: 1773156987006-6kmaw8q │
│ │ Status: Idle │
│ └─────────────────────────────┘
- Click any node on the canvas — the Configuration panel on the right instantly shows its editable fields.
- Fields marked with a red
*are required. - Changing the Node Label renames the card on the canvas in real time.
- The ID and Status at the bottom are read-only metadata.
- Click
×at the top-right of the panel to close it without losing your work.
The toolbar (top bar) shows a live count: 3 nodes 2 edges 3 errors.
- Red error count → click the Validation tab in the bottom panel to see what needs fixing.
- Each error card is clickable — it selects the offending node so you can configure it immediately.
- Error types:
- ⚡ No Trigger — add a Trigger node first
- 🔄 Cycle Detected — remove circular connections
- 📝 Missing Field — fill in all required fields
- 🔌 Disconnected Node — connect all nodes to the graph
When all errors are resolved, the status changes to ✓ Valid in green.
Click ▶ Execute
│
▼
Topological sort runs (Kahn's algorithm)
│
├─ cycle found? → abort, log error
│
▼
Step-by-step async simulation:
[Trigger] → pulsing ring + "running" badge
→ 800ms delay
→ "completed" badge (green ring)
[Send Email] → same cycle
[Delay] → same cycle
│
▼
Execution Log fills up in real time:
✓ [System] Starting execution of 3 node(s)...
✓ [Trigger] Trigger fired: "user.signup" event received
✓ [Send Email] Email sent to ... — Subject: "..."
✓ [Delay] Waited 5 seconds
✓ [System] Workflow completed successfully. 3 node(s) executed.
- The currently running node pulses with a sky-blue ring.
- Completed nodes get a green ring.
- Failed nodes get a red ring and execution stops immediately.
- A progress bar in the bottom panel shows % completion.
| Action | Keyboard | Toolbar |
|---|---|---|
| Undo last change | Ctrl + Z |
↩ Undo button |
| Redo undone change | Ctrl + Y |
↪ Redo button |
Up to 50 steps of history are stored. The history is cleared when you import or reset the workflow.
| Button | What it does |
|---|---|
| Save | Writes the current workflow to localStorage immediately |
| Export | Downloads a .json file of the full workflow snapshot |
| Import | Opens a file picker — load any previously exported .json |
The workflow also auto-saves every 3 seconds after any change. On the next visit, it is restored automatically.
Click the 🌙 / ☀️ button in the top-right corner of the toolbar. Your preference is saved to localStorage and persists across sessions.
┌──────────────────────────────────────────────────────────────────────┐
│ FF FlowForge [Untitled Workflow] Undo Redo │ Save Export Import │ ← Toolbar
│ ▶ Execute 🗑 Reset │ 3n 2e ☀️│
├──────────────┬───────────────────────────────────┬───────────────────┤
│ │ │ CONFIGURATION │
│ NODE LIBRARY │ │ ⚡ Trigger │
│ │ C A N V A S │ │
│ ⚡ Trigger │ ┌──────────────┐ │ Node Label │
│ ✉ Email │ │ Trigger │ │ [Trigger ] │
│ ⏱ Delay │ └──────┬───────┘ │ Event Name * │
│ 🔀 Condition│ │ │ [user.signup ] │
│ 📋 Logger │ ┌──────▼───────┐ │ Description │
│ │ │ Send Email │ │ [ ] │
│ │ └──────┬───────┘ │ │
│ │ │ │ ID: 177315... │
│ │ ┌──────▼───────┐ │ Status: Idle │
│ │ │ Delay │ │ │
│ │ └──────────────┘ │ [MiniMap] │
├──────────────┴───────────────────────────────────┴───────────────────┤
│ ▶ Execution Log ✓ Validation 3 nodes │ ← Bottom tabs
│ ─────────────────────────────────────────────────────────────────── │
│ Idle 0 events │
│ ▶ No execution logs │
│ Press Execute to run the workflow │
└──────────────────────────────────────────────────────────────────────┘
src/
├── types/
│ └── index.ts # NodeType enum, WorkflowNode, ExecutionLog, ValidationError...
├── utils/
│ ├── graphUtils.ts # topologicalSort (Kahn's), detectCycles (DFS), validateWorkflow
│ └── nodeConfigs.ts # Field schemas + display config per node type
├── store/
│ ├── workflowStore.ts # Nodes, edges, undo/redo history (Zustand)
│ ├── executionStore.ts # Execution status, logs, progress (Zustand)
│ └── themeStore.ts # Dark/light mode + localStorage (Zustand persist)
├── features/
│ ├── workflow/WorkflowBuilder.tsx # Root three-panel layout, keyboard shortcuts
│ ├── execution/ExecutionEngine.ts # Async step-by-step simulation
│ ├── validation/ValidationEngine.ts # Validation orchestration layer
│ └── persistence/PersistenceManager.ts # localStorage, version history, JSON I/O
├── components/
│ ├── Canvas.tsx # React Flow canvas + drag-drop handler
│ ├── Sidebar.tsx # Draggable node library (left panel)
│ ├── ConfigPanel.tsx # Dynamic config form (right panel)
│ ├── Toolbar.tsx # All top-bar actions
│ ├── NodeCard.tsx # Custom React Flow node renderer
│ ├── ExecutionPanel.tsx # Real-time execution log with progress bar
│ └── ValidationPanel.tsx # Validation error display
├── hooks/
│ ├── useWorkflowStore.ts # Granular selector hooks
│ ├── useValidation.ts # Memoized validation results
│ ├── useExecutionEngine.ts # Execute / reset wrapper
│ ├── useUndoRedo.ts # Undo/redo state surface
│ └── useLocalPersistence.ts # Auto-save on state change
└── __tests__/
├── graphUtils.test.ts # 15 unit tests for graph algorithms
└── workflowStore.test.ts # 10 unit tests for store + undo/redo
workflowStore—nodes[],edges[],past[],future[]. Every mutation pushes astructuredClonesnapshot to history. Max 50 entries.executionStore—status,logs[],currentNodeId,progress. Owned entirely by the execution engine.themeStore— single booleanisDarkwith Zustandpersistmiddleware.
- Topological Sort — Kahn's BFS algorithm, O(V+E). Returns
nullon cycle. - Cycle Detection — DFS with recursion stack, returns path of cycle nodes.
- Validation — 4-rule pipeline: trigger exists → no cycles → required fields → no orphaned nodes.
Async simulation iterates topologically-sorted nodes with 800ms step delay. Each node status is reflected live on the canvas card via workflowStore.updateNodeStatus.
Auto-save debounced at 3s. Manual save/export/import via PersistenceManager. Last 10 versions stored under flowforge_versions key.
| Shortcut | Action |
|---|---|
Ctrl / Cmd + Z |
Undo |
Ctrl / Cmd + Y |
Redo |
Ctrl / Cmd + Shift + Z |
Redo (alternate) |
| Node | Icon | Required Fields | Description |
|---|---|---|---|
| Trigger | ⚡ | Event Name | Workflow entry point — fires on a named event |
| ✉️ | To, Subject | Sends an email notification | |
| Delay | ⏱️ | Duration, Unit | Pauses execution for a given time |
| Condition | 🔀 | Field, Operator, Value | Branches the flow based on a boolean check |
| Logger | 📋 | Message, Level | Emits a log message at info / warn / error level |
npm run test:run # single CI run
npm test # watch mode
npm run test:ui # Vitest browser UICovers: topological sort, cycle detection, workflow validation, ID generation, store add/remove, undo/redo stacks, config updates.
| Tool | Version | Purpose |
|---|---|---|
| React | 18 | UI rendering |
| TypeScript | 5 (strict) | Type safety |
| Vite | 5 | Dev server + build |
| Zustand | 4 | State management |
| React Flow | 11 | Graph canvas |
| TailwindCSS | 3 | Styling |
| Vitest | 2 | Unit testing |
| clsx | 2 | Conditional classnames |
