SST Flow Builder
A VS Code extension for visually authoring self-service application flows. Flows are stored as .flw files and opened in a custom editor (viewType: sstFlowBuilder.flowEditor) that renders an interactive React Flow canvas.
v1 scope: Editor only — no runtime execution engine in v1.
Node Types
| Type |
Has .ts code |
Purpose |
Key fields |
start |
No |
Flow entry point (one per flow) |
— |
end |
No |
Flow exit (multiple allowed, distinguished by name) |
name? |
operation |
Yes |
Business logic unit; calls context.resolve(event) to pick the outgoing edge |
name |
decision |
Yes |
Branching logic; declares expected outgoing events |
name, branches[] |
subflow |
No |
Calls another flow; the target flow's exits become outgoing events |
name, targetFlow |
shortcut |
No |
Jumps to another node within the same flow |
name, targetNodeId |
Edges carry an event label — the navigation name passed to context.resolve("Continue").
Node Code Files
Node code follows a parallel-tree convention:
<flowsRoot>/<rel>/<Name>.flw → <scriptsRoot>/<rel>/<Name>/<NodeName>.ts
Example:
flows/balance/Balance.flw
└─ operation node "BalanceAuthorise"
→ flow-scripts/balance/Balance/BalanceAuthorise.ts
Default roots: flows and flow-scripts (configurable — see Configuration).
Double-click interactions:
operation / decision node → opens (or creates) its .ts file in the side column.
subflow node → opens the target .flw file.
start / end / shortcut → opens the property panel.
The text document is the single source of truth. Undo/redo, dirty state, and git diff all work normally.
{
"schemaVersion": 1,
"name": "Balance",
"nodes": [
{ "id": "n_start", "type": "start", "position": { "x": 0, "y": 0 } },
{ "id": "n_end", "type": "end", "name": "Close", "position": { "x": 0, "y": 400 } },
{ "id": "n_auth", "type": "operation", "name": "BalanceAuthorise",
"position": { "x": 0, "y": 100 } },
{ "id": "n_check", "type": "decision", "name": "CheckNextAction",
"branches": ["Display", "Print", "Close"],
"position": { "x": 0, "y": 200 } },
{ "id": "n_sel", "type": "subflow", "name": "SelectAccount",
"targetFlow": "common/SelectAccount",
"position": { "x": 0, "y": 150 } },
{ "id": "n_sc", "type": "shortcut", "name": "Close",
"targetNodeId": "n_end",
"position": { "x": 200, "y": 300 } }
],
"edges": [
{ "id": "e1", "source": "n_start", "target": "n_auth", "event": "Continue" },
{ "id": "e2", "source": "n_check", "target": "n_end", "event": "Close" }
]
}
Validation rules (run on open/save; shown as markers on the canvas):
Errors — these mirror the sst-flow-processor runtime's convertFlowDoc, so a flow that fails them here would also be rejected at runtime:
name and id must be unique within a flow.
- Edges and shortcut
targetNodeId references must point to existing nodes.
- Exactly one
start node, and that start node must have exactly one outgoing edge.
- A node may have at most one default exit (an edge with an empty/absent
event).
- A node must not have two outgoing edges with the same non-empty
event (ambiguous routing).
Warnings — advisory only, not enforced at runtime:
decision outgoing edge events should cover (no more, no less than) its branches.
Configuration
| Key |
Default |
Description |
sstFlowBuilder.flowsRoot |
"flows" |
Root folder for .flw files (relative to workspace) |
sstFlowBuilder.scriptsRoot |
"flow-scripts" |
Root folder for node .ts files (relative to workspace) |
sstFlowBuilder.nodeTemplate |
"" |
Path to a custom node code template file (empty = built-in template) |
sstFlowBuilder.layoutDirection |
"TB" |
Auto-layout direction: "TB" (top→bottom) or "LR" (left→right) |
Commands
| Command |
Description |
| SST Flow Builder: Create Scaffold |
Scaffold a minimal TypeScript host project that runs .flw flows via sst-flow-processor (prompts for target directory and framework: Angular / React / Vue / None) |
| SST Flow Builder: New Flow |
Create an empty .flw in flowsRoot and open it |
| SST Flow Builder: Auto Layout |
Run dagre auto-layout on the current flow (also available as a toolbar button) |
| SST Flow Builder: Check Orphan Scripts |
List .ts files with no matching node, and nodes missing a .ts |
| SST Flow Builder: Migrate Script Folder |
Manually sync the scripts directory after renaming/moving a flow file |
Development
Prerequisites
Setup and build
npm install
npm run build # bundles dist/extension.js (host) and dist/webview.js (React canvas)
Tests
npm test # Vitest unit tests (schema, validate, pathMapping, graph, layout, protocol, model, nodeCodeService)
npm run test:int # Headless VS Code integration smoke test (requires display or Xvfb on Linux)
Launch extension
Press F5 in VS Code to open the Extension Development Host with the extension loaded. Open any .flw file to activate the custom editor.
Architecture Overview
- Host (Node.js):
src/extension.ts activates the extension; src/editor/FlowEditorProvider.ts implements CustomTextEditorProvider; src/scripts/ handles path mapping and node code file operations; src/layout/ wraps dagre.
- Webview (React):
webview/main.tsx + webview/FlowCanvas.tsx render the React Flow canvas with custom node components; communicates with the host via typed messages defined in src/shared/schema.ts.
- Build:
esbuild.mjs bundles both targets. The host bundle targets Node; the webview bundle targets the browser.
License
Licensed under the Apache License 2.0. Copyright 2026 Tiejun Hu.