Builder Audit
Comprehensive architecture audit of the workflow builder
Builder: Comprehensive Architecture Audit
Source: This page is based on docs/BUILDER_AUDIT.md
Last Updated: January 20, 2026
Status: š¢ Production Ready - Excellent Architecture & Performance
Entry Point: pages/workspaces/[groupId]/workflows/[workflowId]/index.tsx
Executive Summary
The Builder is Eddy's "Level Editor" - the visual environment where users design and configure workflows.
Current State Assessment
| Area | Grade | Status |
|---|---|---|
| Data Fetching | A- | ā Optimized with lazy loading |
| State Management | A- | ā Consolidated into single store |
| Performance | A- | ā 98% reduction in operations |
| Code Organization | A | ā Modular with extracted hooks |
| Maintainability | A- | ā Clean patterns with testing |
| Separation of Concerns | A- | ā Clear boundaries defined |
Overall Grade: A-/A (Excellent - Production Ready)
Architecture Overview
Component Hierarchy
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā pages/workspaces/[groupId]/workflows/[workflowId]/ ā
ā index.tsx (Entry Point - 457 lines) ā
ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā Data Fetching Layer ā ā
ā ā ⢠useGetWorkflow() ā ā
ā ā ⢠useGetGroupMemberships() ā ā
ā ā ⢠useGetWorkflowRunPreviewByWorkflow() ā ā
ā ā ⢠useGetSheetDataByWorkflowId() (lazy) ā ā
ā ā ⢠useChannel() (Ably real-time) ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā State Management ā ā
ā ā ⢠useWorkflowBuilderStore (builder-specific) ā ā
ā ā ⢠useCommonStore (shared with sessions) ā ā
ā ā ⢠useUIStore (device type) ā ā
ā ā ⢠useStageRoleAssignmentsModalStore ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā Main UI Components ā ā
ā ā ⢠BuilderTopBar (modals, publish, validation) ā ā
ā ā ⢠BuilderStageGraph (visual graph editor) ā ā
ā ā ⢠BuilderPanels (page/section/block editors) ā ā
ā ā ⢠EdgeEditor (connection rule editor) ā ā
ā ā ⢠Modals (Settings, Activity, Data, Sessions) ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā components/builder/BuilderStageGraph.tsx ā
ā (Graph Editor - 685 lines, down from 1,007) ā
ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā Custom Hooks (Extracted) ā ā
ā ā ⢠useGraphMutations (180 lines) - CRUD operations ā ā
ā ā ⢠useGraphLayout (260 lines) - Dagre & animations ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā UI Components (Extracted) ā ā
ā ā ⢠GraphContextMenu (59 lines) - Right-click menu ā ā
ā ā ⢠GraphControlPanels (86 lines) - Layout/zoom ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā Node Types ā ā
ā ā ⢠BuilderGraphNode - Stage node with preview ā ā
ā ā ⢠Custom edge types (smoothstep, looping) ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāKey Responsibilities
Entry Point (index.tsx):
- Data orchestration (fetch workflow, group, preview)
- Permission management (CASL abilities)
- Validation coordination (debounced)
- Modal state management
- Real-time updates (Ably)
- Cleanup on unmount
BuilderStageGraph:
- Visual graph rendering (ReactFlow)
- Node/edge creation and deletion
- Drag-and-drop positioning
- Layout algorithms (Dagre)
- Connection validation
- Animation coordination
BuilderTopBar:
- Workflow metadata display
- Modal triggers (Data, Activity, Settings, Sessions)
- Publish toggle
- Validation error display
- Start menu & options
BuilderPanels:
- Page content editor
- Section editor
- Block editor
- Responsive layout (desktop/mobile)
Data Fetching Strategy
Primary Workflow Data
// Always loaded
const { data: workflow } = useGetWorkflow(workflowId)
const { data: group } = useGetGroupMemberships(groupId)
const { data: preview } = useGetWorkflowRunPreviewByWorkflow(workflowId)
// Lazy loaded (only when needed)
const { data: sheetData } = useGetSheetDataByWorkflowId(workflowId, {
enabled: isDataModalOpen
})Benefits:
- Minimal initial load
- Sheet data loaded only when Data modal opens
- Preview data for session count display
State Management
Zustand Stores
useWorkflowBuilderStore - Builder-specific state:
- Selected page, section, block
- Edge editor state
- Validation errors
- Modal open/closed states
useCommonStore - Shared with sessions:
- User preferences
- UI settings
useUIStore - Device detection:
- Mobile/desktop detection
- Responsive layout decisions
State Organization
// ā
GOOD: Clear state boundaries
const {
selectedPageId,
selectedSectionId,
selectedBlockId,
setSelectedPageId
} = useWorkflowBuilderStore()
// ā BAD: Mixing concerns
const [selectedPageId, setSelectedPageId] = useState()
const [validationErrors, setValidationErrors] = useState()
// ... scattered across componentPerformance Optimizations
Graph Computation
Before Optimization:
- Multiple passes over nodes/edges
- O(N²) operations for styling
- Redundant filtering
After Optimization:
- Single-pass computation
- Pre-computed maps for O(1) lookups
- 98% reduction in operations
Lazy Loading
Sheet Data:
- Only loaded when Data modal opens
- Prevents unnecessary API calls
- Reduces initial bundle size
Validation:
- Debounced validation (500ms)
- Only runs when workflow changes
- Prevents excessive computation
Code Organization
Extracted Hooks
useGraphMutations.ts (180 lines):
createPage()deletePage()createTransition()deleteTransition()- Mutation logic separated from UI
useGraphLayout.ts (260 lines):
- Dagre layout algorithm
- Animation coordination
- Position calculations
- Layout logic separated from rendering
Extracted Components
GraphContextMenu.tsx (59 lines):
- Right-click menu
- Context-aware actions
- Reusable across graph types
GraphControlPanels.tsx (86 lines):
- Layout controls
- Zoom controls
- Fit view buttons
Testing
Unit Tests
Coverage:
- Graph mutations
- Validation logic
- State management
Example:
describe('useGraphMutations', () => {
it('creates page with correct defaults', () => {
const { result } = renderHook(() => useGraphMutations())
const newPage = result.current.createPage()
expect(newPage.title).toBe('New Stage')
expect(newPage.sections).toEqual([])
})
})Integration Tests
Coverage:
- End-to-end builder workflows
- Validation system
- Real-time updates
Improvement History
January 2026 Refactor
Changes:
- Extracted hooks from BuilderStageGraph (1,007 ā 685 lines)
- Consolidated state into Zustand stores
- Optimized graph computation (98% reduction)
- Added comprehensive testing
Impact:
- Improved maintainability
- Better performance
- Easier to onboard new developers
Future Opportunities
1. Mobile Builder Experience
Current State: Desktop-optimized
Opportunity: Improve touch interactions and mobile layout
2. Undo/Redo System
Current State: No undo functionality
Opportunity: Implement command pattern for undo/redo
3. Collaborative Editing
Current State: Real-time updates via Ably
Opportunity: Add conflict resolution and presence indicators
4. Performance Monitoring
Current State: Manual performance testing
Opportunity: Add automated performance regression testing