Phase 27 — Premium Workflow Editor UX
Elevates the Phase 23 visual workflow builder from functional to best-in-class with smart edge routing, ELK.js auto-layout in Web Workers, CodeMirror 6 expression editing with drag-to-map data mapping, real-time execution visualization via SSE, command palette, sticky notes, node grouping, subflow drill-in/drill-out, workflow templates, version diff overlay, collaborative editing, and 40+ micro-interactions that create the perception of a premium, professional tool.
Status: Implemented Depends on: Phase 23 (Visual Workflow Builder), Phase 12 (NATS/SSE), Phase 9 (Tool Registry) Migrations: None (extends Phase 23 schema) Branch: feature-react-ui
Why Now
Phase 23 delivers a complete visual workflow builder with 12 node types, React Flow canvas, Zustand state, schema-driven configuration, live execution, Postgres persistence, and dynamic MCP tool palette. But the gap between "works" and "wow" is substantial. After researching n8n's editor architecture in depth:
- Edge routing is amateur. React Flow's default
SmoothStepedges pass through nodes, creating visual clutter that makes complex workflows unreadable. n8n's canvas uses obstacle-aware orthogonal routing. - No intelligent expression editor. Phase 23B's expression editor is a basic text input. n8n uses CodeMirror 6 with a custom Lezer parser, context-aware autocomplete, inline evaluation preview, and drag-to-map from upstream node outputs.
- No auto-layout. The "Tidy up" operation is the single strongest quality signal in workflow editors. Dagre is inadequate for nested graphs (subflows). ELK.js provides hierarchical layout that handles Cruvero's Subgraph and Parallel primitives correctly.
- Execution visualization is static. Phase 23C overlays status badges. Professional editors use pulsing borders, flowing-dot edge animations, per-node timing badges, and execution timelines — all streamed in real-time via SSE.
- No organizational tools. Sticky notes, node grouping, canvas search, and subflow drill-in/drill-out are essential for workflows with 30+ nodes.
- Missing power-user features. Command palette (
Cmd+K), comprehensive keyboard shortcuts, auto-connect, canvas search (Cmd+F), and inline node renaming (F2) are expected by technical users.
Phase 27 adds these features in four tiers, each independently valuable. n8n built its editor over 6 years — this phase distills the 10 highest-leverage investments for maximum impact in minimum time.
Architecture
Technical Foundation
Phase 27 adds five key libraries to the existing React Flow + Zustand foundation:
| Library | Purpose | License | Size |
|---|---|---|---|
elkjs | Hierarchical auto-layout (layered, stress, mrtree) | EPL-2.0 | ~350KB (Web Worker bundle) |
@codemirror/view + @codemirror/state | Expression editor framework | MIT | ~120KB |
@lezer/common + @lezer/javascript | Expression parser with JS delegation | MIT | ~60KB |
@jalez/react-flow-smart-edge | A* pathfinding edge routing | MIT | ~15KB |
cmdk | Command palette | MIT | ~8KB |
zundo | Zustand temporal middleware (undo/redo) | MIT | ~3KB |
tiptap (@tiptap/react + @tiptap/starter-kit) | Rich-text sticky notes | MIT | ~80KB |
framer-motion | Animated transitions (drill-in/out, layout) | MIT | ~40KB |
yjs + y-websocket | Collaborative CRDT (Tier 4) | MIT | ~25KB |
Canvas Architecture (After Phase 27)
┌─────────────────────────────────────────────────────────────────────────┐
│ FlowBuilderV2Page │
│ │
│ ┌──────────┐ ┌──────────────────────────────────────┐ ┌───────────┐ │
│ │ Node │ │ React Flow Canvas │ │ Inspector │ │
│ │ Palette │ │ │ │ Panel │ │
│ │ + Search│ │ ┌─────────┐ SmartEdge ┌────┐ │ │ │ │
│ │ │ │ │ToolNode ├────────────────►│Join│ │ │ Config │ │
│ │ ───────── │ │ │ │ │ │ │ Tabs │ │
│ │ Canvas │ │ └─────────┘ └────┘ │ │ │ │
│ │ Search │ │ │ │ Expression│ │
│ │ (Cmd+F) │ │ ┌─────────────────┐ StickyNote │ │ Editor │ │
│ │ │ │ │ NodeGroup │ ┌──────────┐ │ │ (CM6) │ │
│ │ ───────── │ │ │ ┌───┐ ┌───┐ │ │ Markdown │ │ │ │ │
│ │ Command │ │ │ │ A │──│ B │ │ │ via │ │ │ Data │ │
│ │ Palette │ │ │ └───┘ └───┘ │ │ TipTap │ │ │ Preview │ │
│ │ (Cmd+K) │ │ └─────────────────┘ └──────────┘ │ │ (drag-map)│ │
│ └──────────┘ │ │ └───────────┘ │
│ │ ┌────────────────────────────────┐ │ │
│ Toolbar │ │ Breadcrumb: Root > Group > Sub │ │ │
│ ┌──────────┐ │ └────────────────────────────────┘ │ │
│ │Tidy|Run| │ │ │ │
│ │Undo|Save │ │ ┌────────── Minimap ──────────┐ │ │
│ └──────────┘ │ └──────────────────────────────┘ │ │
│ └──────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Execution Timeline / History Panel (collapsible) │ │
│ │ [Step1 ✓ 120ms] [Step2 ✓ 340ms] [Step3 ✗ Error] [Step4 ⏳] │ │
│ └──────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
Web Worker Architecture
Main Thread Web Workers
┌──────────────────────┐ ┌─────────────────────┐
│ React Flow Canvas │ postMessage │ ELK Layout Worker │
│ + Zustand Store ├────────────►│ - elkjs import │
│ │◄────────────┤ - computeLayout() │
│ │ positions │ - incremental mode │
│ │ └─────────────────────┘
│ │ ┌─────────────────────┐
│ │ postMessage │ Validation Worker │
│ ├────────────►│ - cycle detection │
│ │◄────────────┤ - DSL compilation │
│ │ errors │ - expression parse │
│ │ └─────────────────────┘
└──────────────────────┘
Four-Tier Implementation
Tier 1 — Table Stakes (Sub-phases A + B):
1.1 Smart Edge Routing (A* pathfinding)
1.2 ELK.js Auto-Layout in Web Worker
1.3 Undo/Redo via zundo
1.4 Command Palette (cmdk)
1.5 Comprehensive Keyboard Shortcuts
1.6 Snap/Alignment Guides
1.7 Connection Validation with Visual Feedback
Tier 2 — Differentiating (Sub-phases C + D):
2.1 CodeMirror 6 Expression Editor with Lezer Parser
2.2 Drag-to-Map Data Mapping
2.3 Three-Panel Node Details View (Input | Config | Output)
2.4 Data Preview (Table/JSON/Schema views)
2.5 Sticky Notes with TipTap Rich Text
2.6 Node Comments (inline + expandable)
2.7 Canvas Search (Cmd+F) with Spotlight Mode
2.8 Node Grouping with parentId API
Tier 3 — Premium Polish (Sub-phases E + F):
3.1 Subflow Drill-In/Drill-Out with Breadcrumbs
3.2 Workflow Templates Gallery
3.3 Version Diff Overlay on Canvas
3.4 Enhanced Execution Visualization (pulsing borders, flowing dots)
3.5 Execution Timeline with Per-Node Timing
3.6 Auto-Connect (node picker auto-wires to selected)
3.7 Inline Node Renaming (F2)
Tier 4 — Enterprise (Sub-phase G):
4.1 Collaborative Editing (Yjs + y-websocket)
4.2 Multiplayer Cursors + Presence Indicators
4.3 Follow Mode (track another user's viewport)
4.4 Conflict Resolution for Concurrent Edits
Sub-Phases
| Sub-Phase | Name | Prompts | Depends On |
|---|---|---|---|
| 27A | Smart Edges + Auto-Layout | 4 | Phase 23A |
| 27B | Keyboard UX + Command Palette | 3 | Phase 23A |
| 27C | CodeMirror Expression Editor + Data Mapping | 5 | Phase 23B |
| 27D | Sticky Notes + Grouping + Canvas Search | 4 | Phase 23A |
| 27E | Execution Visualization + Timeline | 4 | Phase 23C |
| 27F | Subflows + Templates + Version Diff | 4 | 27A, Phase 23D |
| 27G | Collaborative Editing | 3 | 27A–27F |
| 27H | CI/CD + Deployment (y-websocket + Templates) | 3 | 27F, 27G |
Total: 8 sub-phases, 30 prompts
Dependency Graph
Phase 23A ──► 27A (Smart Edges + Layout) ──┬──► 27F (Subflows + Templates + Diff) ──┐
│ │ │
Phase 23A ──► 27B (Keyboard + Cmd Palette) │ ├──► 27H (CI/CD + Deploy)
│ │ │
Phase 23B ──► 27C (Expression Editor) ├──► 27G (Collaborative) ───────────────┘
│ │
Phase 23A ──► 27D (Sticky + Groups + Search)│
│ │
Phase 23C ──► 27E (Exec Viz + Timeline) ────┘
27A–27E are parallelizable (each only depends on Phase 23 sub-phases). 27F depends on 27A. 27G depends on all prior sub-phases. 27H depends on 27F and 27G (deployment of their artifacts).
New Dependencies
| Library | Version | License | Purpose |
|---|---|---|---|
elkjs | ^0.9.3 | EPL-2.0 | Hierarchical graph layout |
@codemirror/view | ^6.x | MIT | Editor framework |
@codemirror/state | ^6.x | MIT | Editor state management |
@codemirror/autocomplete | ^6.x | MIT | Autocomplete extension |
@codemirror/lang-javascript | ^6.x | MIT | JS syntax highlighting |
@lezer/common | ^1.x | MIT | Parser framework |
@lezer/javascript | ^1.x | MIT | JS grammar for parseMixed |
@jalez/react-flow-smart-edge | ^3.x | MIT | A* edge routing for React Flow v12 |
cmdk | ^1.x | MIT | Command palette |
zundo | ^2.x | MIT | Zustand temporal middleware |
@tiptap/react | ^2.x | MIT | Rich-text editor for sticky notes |
@tiptap/starter-kit | ^2.x | MIT | TipTap base extensions |
framer-motion | ^11.x | MIT | Animation transitions |
yjs | ^13.x | MIT | CRDT for collaborative editing |
y-websocket | ^2.x | MIT | Yjs WebSocket provider |
Environment Variables
| Variable | Default | Description |
|---|---|---|
CRUVERO_FLOW_ELK_ALGORITHM | layered | ELK layout algorithm (layered, stress, mrtree, radial) |
CRUVERO_FLOW_ELK_DIRECTION | DOWN | Layout direction (DOWN, RIGHT, LEFT, UP) |
CRUVERO_FLOW_ELK_SPACING | 80 | Node spacing in pixels |
CRUVERO_FLOW_SMART_EDGES | true | Enable A* smart edge routing |
CRUVERO_FLOW_SNAP_GRID | 20 | Grid snap size in pixels (0 = disabled) |
CRUVERO_FLOW_UNDO_DEPTH | 50 | Max undo/redo stack depth |
CRUVERO_FLOW_COLLAB_ENABLED | false | Enable collaborative editing |
CRUVERO_FLOW_COLLAB_WS_URL | ws://localhost:1234 | Yjs WebSocket server URL |
CRUVERO_FLOW_TEMPLATES_DIR | templates/workflows | Directory for workflow templates |
Files Overview
New Files
| File | Sub-Phase | Description |
|---|---|---|
cmd/ui/frontend/src/lib/elk-layout-worker.ts | 27A | Web Worker for ELK.js layout computation |
cmd/ui/frontend/src/hooks/useAutoLayout.ts | 27A | React hook wrapping ELK Worker communication |
cmd/ui/frontend/src/components/flow-v2/edges/SmartEdge.tsx | 27A | Smart edge wrapper using @jalez/react-flow-smart-edge |
cmd/ui/frontend/src/components/flow-v2/edges/AnimatedFlowEdge.tsx | 27E | Edge with SVG dot particles for execution |
cmd/ui/frontend/src/lib/snap-guides.ts | 27A | Snap alignment guide calculations |
cmd/ui/frontend/src/components/flow-v2/canvas/AlignmentGuides.tsx | 27A | Visual guide lines during drag |
cmd/ui/frontend/src/components/flow-v2/CommandPalette.tsx | 27B | cmdk-based command palette |
cmd/ui/frontend/src/hooks/useFlowShortcuts.ts | 27B | Comprehensive keyboard shortcut handler |
cmd/ui/frontend/src/components/flow-v2/config/ExpressionEditorV2.tsx | 27C | CodeMirror 6 expression editor |
cmd/ui/frontend/src/lib/lezer-cruvero-expr.ts | 27C | Custom Lezer grammar for {{ }} expressions |
cmd/ui/frontend/src/lib/expression-completions.ts | 27C | Autocomplete sources (upstream data, builtins) |
cmd/ui/frontend/src/components/flow-v2/config/DataPreview.tsx | 27C | Table/JSON/Schema output views |
cmd/ui/frontend/src/components/flow-v2/config/DragToMap.tsx | 27C | Draggable field → expression drop targets |
cmd/ui/frontend/src/components/flow-v2/config/NodeDetailsView.tsx | 27C | Three-panel NDV (Input / Config / Output) |
cmd/ui/frontend/src/components/flow-v2/canvas/StickyNote.tsx | 27D | Custom React Flow node with TipTap |
cmd/ui/frontend/src/components/flow-v2/canvas/NodeGroup.tsx | 27D | Group node with NodeResizer |
cmd/ui/frontend/src/components/flow-v2/canvas/CanvasSearch.tsx | 27D | Cmd+F search with spotlight mode |
cmd/ui/frontend/src/components/flow-v2/canvas/NodeComment.tsx | 27D | Inline subtitle + expandable popup |
cmd/ui/frontend/src/components/flow-v2/execution/ExecutionParticles.tsx | 27E | SVG dot particles along edges |
cmd/ui/frontend/src/components/flow-v2/execution/NodeStatusOverlay.tsx | 27E | Pulsing borders + timing badges |
cmd/ui/frontend/src/components/flow-v2/execution/ExecutionTimelineV2.tsx | 27E | Horizontal timeline with per-node timing |
cmd/ui/frontend/src/hooks/useExecutionSSE.ts | 27E | SSE client for execution events |
cmd/ui/frontend/src/components/flow-v2/navigation/SubflowBreadcrumb.tsx | 27F | Breadcrumb navigation bar |
cmd/ui/frontend/src/hooks/useSubflowNavigation.ts | 27F | Navigation stack in Zustand |
cmd/ui/frontend/src/components/flow-v2/templates/TemplateGalleryV2.tsx | 27F | Template browser with preview thumbnails |
cmd/ui/frontend/src/components/flow-v2/diff/VersionDiffOverlay.tsx | 27F | Canvas diff: added/removed/modified nodes |
cmd/ui/frontend/src/lib/flow-diff.ts | 27F | Workflow version comparison logic |
cmd/ui/frontend/src/components/flow-v2/collab/CollabProvider.tsx | 27G | Yjs provider wrapper |
cmd/ui/frontend/src/components/flow-v2/collab/RemoteCursors.tsx | 27G | Multiplayer cursor rendering |
cmd/ui/frontend/src/components/flow-v2/collab/PresenceBar.tsx | 27G | Online users indicator |
cmd/ui/frontend/src/hooks/useCollaboration.ts | 27G | Yjs sync hook for nodes/edges |
cmd/ui/collab_ws_handler.go | 27G | WebSocket proxy for y-websocket |
Modified Files
| File | Sub-Phase | Change |
|---|---|---|
cmd/ui/frontend/src/stores/flow-builder.ts | 27A, 27B | Add zundo middleware, snap state, collab awareness |
cmd/ui/frontend/src/components/flow-v2/Canvas.tsx | 27A | Wire SmartEdge, alignment guides, snap grid |
cmd/ui/frontend/src/components/flow-v2/Toolbar.tsx | 27A, 27B | Add Tidy Up, Cmd+K, undo/redo buttons |
cmd/ui/frontend/src/components/flow-v2/edges/edgeTypes.ts | 27A, 27E | Register SmartEdge and AnimatedFlowEdge |
cmd/ui/frontend/src/components/flow-v2/nodes/nodeTypes.ts | 27D | Register StickyNote, NodeGroup |
cmd/ui/frontend/src/components/flow-v2/config/ExpressionEditor.tsx | 27C | Replace with CodeMirror 6 |
cmd/ui/frontend/src/pages/FlowBuilderV2Page.tsx | 27B, 27D, 27F | Add CommandPalette, CanvasSearch, Breadcrumb |
cmd/ui/frontend/src/types/flow-builder.ts | 27D | Add StickyNoteData, NodeGroupData, CommentData types |
cmd/ui/frontend/package.json | 27A | Add all new dependencies |
cmd/ui/main.go | 27G | Register WebSocket handler for collab |
Referenced (read, not modified)
| File | Purpose |
|---|---|
cmd/ui/frontend/src/components/flow-v2/nodes/FlowNode.tsx | Base node pattern |
cmd/ui/frontend/src/lib/flow-compiler.ts | Compiler for version diff |
cmd/ui/frontend/src/api/workflow-execution.ts | Execution API for SSE |
internal/graph/types.go | Graph DSL for compiler alignment |
Success Metrics
| Metric | Target |
|---|---|
| Auto-layout time (50 nodes) | < 200ms (ELK Worker) |
| Auto-layout time (200 nodes) | < 2s (ELK Worker) |
| Smart edge routing (no overlap) | 0 edge-through-node intersections |
| Expression autocomplete latency | < 100ms from keystroke to suggestions |
| Expression drag-to-map | Field drop → expression insertion < 50ms |
| Undo/redo stack depth | 50 states with < 5ms per undo |
| Command palette open time | < 100ms from Cmd+K to visible |
| Canvas search results | < 50ms fuzzy match across 200 nodes |
| Execution SSE latency | < 200ms from Temporal event to canvas update |
| Sticky note rich text | TipTap renders Markdown in < 16ms |
| Subflow drill-in transition | 300ms animated zoom |
| Template load time | < 500ms from click to canvas populated |
| Version diff computation | < 100ms for 100-node workflows |
| Collaborative sync latency | < 100ms Yjs CRDT convergence |
| Bundle size (flow builder page) | < 150KB gzipped (lazy-loaded) |
| Frame rate during drag | 60fps with 100 nodes |
| Memory usage (200 nodes) | < 100MB heap |
| Frontend unit test coverage | >= 80% (vitest, flow-v2 components) |
| Backend handler test coverage | >= 80% (go test, 27F/27G Go code) |
Code Quality Requirements (SonarQube)
Frontend (All Sub-Phases)
- Build:
npm run buildmust succeed without errors or warnings. - Type checking:
npx tsc --noEmitpasses — strict mode, no TypeScript errors. - ESLint: All new
.tsx/.tsfiles pass existing ESLint config without warnings. - No
anytypes: Strict mode enforced — discriminated unions, explicit return types on API functions. - Component size: No single component file exceeds 50 lines of JSX (extract sub-components).
- React.memo: Every custom node and edge component wrapped in
React.memo. - Zustand selectors: Granular selectors — never subscribe to full nodes/edges array in render paths.
- Bundle splitting: ELK, CodeMirror, TipTap, Yjs lazy-loaded via dynamic imports.
- Accessibility: Keyboard-navigable palette, ARIA labels on toolbar buttons, focus management.
- Web Workers: ELK Worker uses
comlinkor rawpostMessagewith typed message protocol. - Vitest: Coverage reporter configured with
v8provider,lcovoutput for SonarQube.
Backend (27F and 27G Go Code)
- Build:
go build ./cmd/ui/passes without errors. - Vet:
go vet ./cmd/ui/...reports no issues. - Static analysis:
staticcheck ./cmd/ui/...passes. - Lint:
golangci-lint run ./cmd/ui/...passes. - Function size: No function exceeds 50 lines.
- Error handling: No
_ = err— all errors checked or explicitly documented. - Test coverage:
go test -coverprofileachieves >= 80% on new Go files.
Risk Mitigation
| Risk | Mitigation |
|---|---|
| ELK.js EPL-2.0 license | EPL-2.0 allows use as a dependency in BSL-licensed software. No code modification needed. |
| Smart edge performance with 100+ edges | @jalez/react-flow-smart-edge grid resolution tunable. Fall back to SmoothStep above 150 edges. |
| CodeMirror 6 bundle size | Lazy-load via dynamic import. Only loaded when expression field is focused. |
| Web Worker communication overhead | Batch layout requests. Debounce 100ms on drag-triggered relayouts. |
| Yjs conflict resolution | CRDTs are mathematically convergent. Concurrent edits produce consistent state without manual resolution. |
| TipTap in custom React Flow nodes | TipTap renders as controlled component inside node. Pointer events isolated to prevent canvas drag interference. |
| Frame drops with execution animations | Use CSS will-change: transform on animated edges. Cap particles at 6 per edge. Use requestAnimationFrame batching. |
| Template gallery stale content | Templates are JSON files in repo. Versioned alongside code. No external dependency. |
Relationship to Other Phases
| Phase | Relationship |
|---|---|
| Phase 23 (Visual Workflow Builder) | 27 extends 23's canvas, nodes, execution, and persistence. No breaking changes. |
| Phase 20 (React UI) | 27 shares routing and component patterns. |
| Phase 12 (NATS/SSE) | 27E execution streaming uses Phase 12's SSE infrastructure. |
| Phase 3 (Graph DSL) | 27F version diff operates on the DSL produced by Phase 23D's compiler. |
| Phase 22 (UI Remediation) | 27 builds on 22's test infrastructure and component library. |
| Phase 26 (Prompt Library v2) | Orthogonal — prompt management and workflow editing are independent. |
Progress Notes
- 2026-02-15 to 2026-02-16: Sub-phases 27A-27H implemented incrementally (layout/smart edges, keyboard UX, expression/data mapping, grouping/search/comments, execution visualization/timeline, subflows/templates/diff, collaboration, and CI/CD deployment wiring).
- 2026-02-16: Closeout completed for remaining Phase 27 gaps:
- subgraph drill-in now loads referenced workflows (no placeholder),
- Flow Builder v2 Execute wired to
/api/executefrom toolbar, command palette, and shortcuts with run stream targeting, - template API/config/runtime routing finalized and tested.