Skip to main content
neutral

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:

  1. Edge routing is amateur. React Flow's default SmoothStep edges pass through nodes, creating visual clutter that makes complex workflows unreadable. n8n's canvas uses obstacle-aware orthogonal routing.
  2. 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.
  3. 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.
  4. 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.
  5. No organizational tools. Sticky notes, node grouping, canvas search, and subflow drill-in/drill-out are essential for workflows with 30+ nodes.
  6. 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:

LibraryPurposeLicenseSize
elkjsHierarchical auto-layout (layered, stress, mrtree)EPL-2.0~350KB (Web Worker bundle)
@codemirror/view + @codemirror/stateExpression editor frameworkMIT~120KB
@lezer/common + @lezer/javascriptExpression parser with JS delegationMIT~60KB
@jalez/react-flow-smart-edgeA* pathfinding edge routingMIT~15KB
cmdkCommand paletteMIT~8KB
zundoZustand temporal middleware (undo/redo)MIT~3KB
tiptap (@tiptap/react + @tiptap/starter-kit)Rich-text sticky notesMIT~80KB
framer-motionAnimated transitions (drill-in/out, layout)MIT~40KB
yjs + y-websocketCollaborative 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-PhaseNamePromptsDepends On
27ASmart Edges + Auto-Layout4Phase 23A
27BKeyboard UX + Command Palette3Phase 23A
27CCodeMirror Expression Editor + Data Mapping5Phase 23B
27DSticky Notes + Grouping + Canvas Search4Phase 23A
27EExecution Visualization + Timeline4Phase 23C
27FSubflows + Templates + Version Diff427A, Phase 23D
27GCollaborative Editing327A–27F
27HCI/CD + Deployment (y-websocket + Templates)327F, 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

LibraryVersionLicensePurpose
elkjs^0.9.3EPL-2.0Hierarchical graph layout
@codemirror/view^6.xMITEditor framework
@codemirror/state^6.xMITEditor state management
@codemirror/autocomplete^6.xMITAutocomplete extension
@codemirror/lang-javascript^6.xMITJS syntax highlighting
@lezer/common^1.xMITParser framework
@lezer/javascript^1.xMITJS grammar for parseMixed
@jalez/react-flow-smart-edge^3.xMITA* edge routing for React Flow v12
cmdk^1.xMITCommand palette
zundo^2.xMITZustand temporal middleware
@tiptap/react^2.xMITRich-text editor for sticky notes
@tiptap/starter-kit^2.xMITTipTap base extensions
framer-motion^11.xMITAnimation transitions
yjs^13.xMITCRDT for collaborative editing
y-websocket^2.xMITYjs WebSocket provider

Environment Variables

VariableDefaultDescription
CRUVERO_FLOW_ELK_ALGORITHMlayeredELK layout algorithm (layered, stress, mrtree, radial)
CRUVERO_FLOW_ELK_DIRECTIONDOWNLayout direction (DOWN, RIGHT, LEFT, UP)
CRUVERO_FLOW_ELK_SPACING80Node spacing in pixels
CRUVERO_FLOW_SMART_EDGEStrueEnable A* smart edge routing
CRUVERO_FLOW_SNAP_GRID20Grid snap size in pixels (0 = disabled)
CRUVERO_FLOW_UNDO_DEPTH50Max undo/redo stack depth
CRUVERO_FLOW_COLLAB_ENABLEDfalseEnable collaborative editing
CRUVERO_FLOW_COLLAB_WS_URLws://localhost:1234Yjs WebSocket server URL
CRUVERO_FLOW_TEMPLATES_DIRtemplates/workflowsDirectory for workflow templates

Files Overview

New Files

FileSub-PhaseDescription
cmd/ui/frontend/src/lib/elk-layout-worker.ts27AWeb Worker for ELK.js layout computation
cmd/ui/frontend/src/hooks/useAutoLayout.ts27AReact hook wrapping ELK Worker communication
cmd/ui/frontend/src/components/flow-v2/edges/SmartEdge.tsx27ASmart edge wrapper using @jalez/react-flow-smart-edge
cmd/ui/frontend/src/components/flow-v2/edges/AnimatedFlowEdge.tsx27EEdge with SVG dot particles for execution
cmd/ui/frontend/src/lib/snap-guides.ts27ASnap alignment guide calculations
cmd/ui/frontend/src/components/flow-v2/canvas/AlignmentGuides.tsx27AVisual guide lines during drag
cmd/ui/frontend/src/components/flow-v2/CommandPalette.tsx27Bcmdk-based command palette
cmd/ui/frontend/src/hooks/useFlowShortcuts.ts27BComprehensive keyboard shortcut handler
cmd/ui/frontend/src/components/flow-v2/config/ExpressionEditorV2.tsx27CCodeMirror 6 expression editor
cmd/ui/frontend/src/lib/lezer-cruvero-expr.ts27CCustom Lezer grammar for {{ }} expressions
cmd/ui/frontend/src/lib/expression-completions.ts27CAutocomplete sources (upstream data, builtins)
cmd/ui/frontend/src/components/flow-v2/config/DataPreview.tsx27CTable/JSON/Schema output views
cmd/ui/frontend/src/components/flow-v2/config/DragToMap.tsx27CDraggable field → expression drop targets
cmd/ui/frontend/src/components/flow-v2/config/NodeDetailsView.tsx27CThree-panel NDV (Input / Config / Output)
cmd/ui/frontend/src/components/flow-v2/canvas/StickyNote.tsx27DCustom React Flow node with TipTap
cmd/ui/frontend/src/components/flow-v2/canvas/NodeGroup.tsx27DGroup node with NodeResizer
cmd/ui/frontend/src/components/flow-v2/canvas/CanvasSearch.tsx27DCmd+F search with spotlight mode
cmd/ui/frontend/src/components/flow-v2/canvas/NodeComment.tsx27DInline subtitle + expandable popup
cmd/ui/frontend/src/components/flow-v2/execution/ExecutionParticles.tsx27ESVG dot particles along edges
cmd/ui/frontend/src/components/flow-v2/execution/NodeStatusOverlay.tsx27EPulsing borders + timing badges
cmd/ui/frontend/src/components/flow-v2/execution/ExecutionTimelineV2.tsx27EHorizontal timeline with per-node timing
cmd/ui/frontend/src/hooks/useExecutionSSE.ts27ESSE client for execution events
cmd/ui/frontend/src/components/flow-v2/navigation/SubflowBreadcrumb.tsx27FBreadcrumb navigation bar
cmd/ui/frontend/src/hooks/useSubflowNavigation.ts27FNavigation stack in Zustand
cmd/ui/frontend/src/components/flow-v2/templates/TemplateGalleryV2.tsx27FTemplate browser with preview thumbnails
cmd/ui/frontend/src/components/flow-v2/diff/VersionDiffOverlay.tsx27FCanvas diff: added/removed/modified nodes
cmd/ui/frontend/src/lib/flow-diff.ts27FWorkflow version comparison logic
cmd/ui/frontend/src/components/flow-v2/collab/CollabProvider.tsx27GYjs provider wrapper
cmd/ui/frontend/src/components/flow-v2/collab/RemoteCursors.tsx27GMultiplayer cursor rendering
cmd/ui/frontend/src/components/flow-v2/collab/PresenceBar.tsx27GOnline users indicator
cmd/ui/frontend/src/hooks/useCollaboration.ts27GYjs sync hook for nodes/edges
cmd/ui/collab_ws_handler.go27GWebSocket proxy for y-websocket

Modified Files

FileSub-PhaseChange
cmd/ui/frontend/src/stores/flow-builder.ts27A, 27BAdd zundo middleware, snap state, collab awareness
cmd/ui/frontend/src/components/flow-v2/Canvas.tsx27AWire SmartEdge, alignment guides, snap grid
cmd/ui/frontend/src/components/flow-v2/Toolbar.tsx27A, 27BAdd Tidy Up, Cmd+K, undo/redo buttons
cmd/ui/frontend/src/components/flow-v2/edges/edgeTypes.ts27A, 27ERegister SmartEdge and AnimatedFlowEdge
cmd/ui/frontend/src/components/flow-v2/nodes/nodeTypes.ts27DRegister StickyNote, NodeGroup
cmd/ui/frontend/src/components/flow-v2/config/ExpressionEditor.tsx27CReplace with CodeMirror 6
cmd/ui/frontend/src/pages/FlowBuilderV2Page.tsx27B, 27D, 27FAdd CommandPalette, CanvasSearch, Breadcrumb
cmd/ui/frontend/src/types/flow-builder.ts27DAdd StickyNoteData, NodeGroupData, CommentData types
cmd/ui/frontend/package.json27AAdd all new dependencies
cmd/ui/main.go27GRegister WebSocket handler for collab

Referenced (read, not modified)

FilePurpose
cmd/ui/frontend/src/components/flow-v2/nodes/FlowNode.tsxBase node pattern
cmd/ui/frontend/src/lib/flow-compiler.tsCompiler for version diff
cmd/ui/frontend/src/api/workflow-execution.tsExecution API for SSE
internal/graph/types.goGraph DSL for compiler alignment

Success Metrics

MetricTarget
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-mapField drop → expression insertion < 50ms
Undo/redo stack depth50 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 textTipTap renders Markdown in < 16ms
Subflow drill-in transition300ms 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 drag60fps 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 build must succeed without errors or warnings.
  • Type checking: npx tsc --noEmit passes — strict mode, no TypeScript errors.
  • ESLint: All new .tsx/.ts files pass existing ESLint config without warnings.
  • No any types: 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 comlink or raw postMessage with typed message protocol.
  • Vitest: Coverage reporter configured with v8 provider, lcov output 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 -coverprofile achieves >= 80% on new Go files.

Risk Mitigation

RiskMitigation
ELK.js EPL-2.0 licenseEPL-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 sizeLazy-load via dynamic import. Only loaded when expression field is focused.
Web Worker communication overheadBatch layout requests. Debounce 100ms on drag-triggered relayouts.
Yjs conflict resolutionCRDTs are mathematically convergent. Concurrent edits produce consistent state without manual resolution.
TipTap in custom React Flow nodesTipTap renders as controlled component inside node. Pointer events isolated to prevent canvas drag interference.
Frame drops with execution animationsUse CSS will-change: transform on animated edges. Cap particles at 6 per edge. Use requestAnimationFrame batching.
Template gallery stale contentTemplates are JSON files in repo. Versioned alongside code. No external dependency.

Relationship to Other Phases

PhaseRelationship
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/execute from toolbar, command palette, and shortcuts with run stream targeting,
    • template API/config/runtime routing finalized and tested.