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/decisionnode → opens (or creates) its.tsfile in the side column.subflownode → opens the target.flwfile.start/end/shortcut→ opens the property panel.
.flw File Format
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:
nameandidmust be unique within a flow.- Edges and shortcut
targetNodeIdreferences must point to existing nodes. - Exactly one
startnode, and thatstartnode 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:
decisionoutgoing edge events should cover (no more, no less than) itsbranches.
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
- Node.js ≥ 18
- VS Code
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.tsactivates the extension;src/editor/FlowEditorProvider.tsimplementsCustomTextEditorProvider;src/scripts/handles path mapping and node code file operations;src/layout/wraps dagre. - Webview (React):
webview/main.tsx+webview/FlowCanvas.tsxrender the React Flow canvas with custom node components; communicates with the host via typed messages defined insrc/shared/schema.ts. - Build:
esbuild.mjsbundles 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.