This document describes the React-based user interface layer of the Sim platform, covering the visual workflow editor, navigation components, and state management architecture. The UI is built around a canvas-based workflow editor with real-time collaboration support.
For details on specific UI subsystems, see:
The UI is organized into three main visual regions: a collapsible sidebar for navigation, a central workflow canvas for visual editing, and a panel system for configuration and tools.
Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:1-97, apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx:63-80
The UI uses Zustand stores for state management, with distinct stores for different concerns. All stores support real-time collaboration through the operation queue system.
Sources: apps/sim/stores/workflows/workflow/store.ts104-107 apps/sim/stores/workflows/registry/store.ts70-80 apps/sim/stores/workflows/subblock/store.ts apps/sim/stores/operation-queue/store.ts34-38 apps/sim/hooks/use-collaborative-workflow.ts33-58
The workflow canvas is built on ReactFlow, a graph visualization library. Custom node and edge types render workflow blocks and connections.
The WorkflowBlock component is the primary node type, rendering functional blocks with configuration sub-blocks. Each block can have multiple handles for different connection types (default, error, conditional).
Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:198-212, apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx:658-662
Block dimensions are centralized in a constants file to ensure consistency across the UI and autolayout systems.
| Constant | Value | Usage |
|---|---|---|
BLOCK_DIMENSIONS.FIXED_WIDTH | 250px | All workflow blocks |
BLOCK_DIMENSIONS.HEADER_HEIGHT | 40px | Block header area |
BLOCK_DIMENSIONS.MIN_HEIGHT | 100px | Minimum block height |
CONTAINER_DIMENSIONS.DEFAULT_WIDTH | 500px | Loop/parallel containers |
CONTAINER_DIMENSIONS.DEFAULT_HEIGHT | 300px | Loop/parallel containers |
CONTAINER_DIMENSIONS.HEADER_HEIGHT | 50px | Container header |
HANDLE_POSITIONS.DEFAULT_Y_OFFSET | 20px | Standard handle position |
Sources: apps/sim/lib/workflows/blocks/block-dimensions.ts10-47
The WorkflowBlock component is responsible for rendering individual blocks on the canvas, including their sub-blocks, handles, and visual states.
The getDisplayValue function intelligently formats sub-block values for display on the canvas, handling complex nested structures.
The sidebar provides workspace and workflow navigation with a resizable width that persists across sessions.
The sidebar width is controlled by a CSS variable --sidebar-width that is set by a blocking script in the layout to prevent hydration mismatches. The resize handler updates both the store and the CSS variable.
Sources: apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx:63-100, apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx:480-679
The sidebar uses a CSS-based approach to avoid hydration mismatches:
layout.tsx reads localStorage and sets --sidebar-width CSS variable before React hydrateslocalStorage via Zustand persist middlewareSources: apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx:52-60, apps/sim/stores/sidebar/store.ts
The workflow canvas supports a rich set of interactions including drag-and-drop, selection, copy/paste, and context menus.
Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:1343-1450, apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:611-698
Copy/paste operations use a clipboard stored in useWorkflowRegistry with validation to prevent trigger conflicts.
| Operation | Function | Validation |
|---|---|---|
| Copy | copyBlocks(blockIds) | Serializes blocks, edges, subflows, and subblock values |
| Paste | executePasteOperation('paste', offset) | Validates trigger constraints, regenerates IDs |
| Duplicate | executePasteOperation('duplicate', offset) | Same validation as paste |
| Cut | Not implemented | Users delete after copying |
Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:894-948, apps/sim/stores/workflows/registry/store.ts626-745
Context menus provide quick access to common operations. The menu position is tracked by useCanvasContextMenu hook, which manages the menu state and selected blocks.
Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:882-1012, apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-canvas-context-menu.ts
The UI supports real-time collaborative editing through an operation queue system that synchronizes changes via Socket.io.
Sources: apps/sim/hooks/use-collaborative-workflow.ts626-671 apps/sim/hooks/use-collaborative-workflow.ts165-434 apps/sim/stores/operation-queue/store.ts34-139
Operations are categorized by target entity and operation type:
| Target | Operations | Payload Example |
|---|---|---|
BLOCK | UPDATE_NAME, UPDATE_ADVANCED_MODE, UPDATE_CANONICAL_MODE | {id, name} |
BLOCKS | BATCH_ADD_BLOCKS, BATCH_REMOVE_BLOCKS, BATCH_UPDATE_POSITIONS, BATCH_UPDATE_PARENT, BATCH_TOGGLE_ENABLED, BATCH_TOGGLE_HANDLES | {blocks: [...], edges: [...]} |
EDGES | BATCH_ADD_EDGES, BATCH_REMOVE_EDGES | {edges: [...]} or {ids: [...]} |
SUBFLOW | UPDATE | {id, type, config} |
SUBBLOCK | SUBBLOCK_UPDATE | {blockId, subblockId, value} |
VARIABLE | ADD, UPDATE, REMOVE | {variableId, field, value} |
WORKFLOW | REPLACE_STATE | {state: {...}} |
Sources: apps/sim/socket/constants.ts apps/sim/hooks/use-collaborative-workflow.ts178-343
The panel system provides contextual configuration and tool interfaces. Panels can be opened/closed and are managed by dedicated stores.
Panel visibility is controlled by keyboard shortcuts and context menu actions. For example, pressing Cmd+K opens the search modal, and right-clicking on the canvas provides a context menu to toggle variables and chat panels.
Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:999-1007, apps/sim/stores/panel/
SubBlocks are the individual input fields within a block's configuration panel. Each SubBlock has a specific type that determines its rendering and behavior.
The platform supports 40+ SubBlock types for different input scenarios:
| Category | Types | Description |
|---|---|---|
| Text Input | short-input, long-input, code | Single-line, multi-line, and code editors |
| Selection | dropdown, combobox, checkbox-list, grouped-checkbox-list | Dropdowns, multi-select lists |
| Specialized Input | slider, table, switch, time-input, file-upload | Numeric ranges, grids, toggles |
| Conditional Logic | condition-input, eval-input, router-input | Complex branching logic |
| AI/Tools | tool-input, messages-input, response-format, input-format | LLM configuration, structured data |
| OAuth/Credentials | oauth-input | OAuth credential selection |
| Selectors | file-selector, sheet-selector, channel-selector, user-selector, folder-selector, project-selector, knowledge-base-selector, document-selector, workflow-selector, mcp-server-selector, mcp-tool-selector | Service-specific entity pickers |
| Knowledge Base | knowledge-tag-filters, document-tag-entry | RAG integration |
| Workflow | input-mapping, variables-input, workflow-input-mapper | Workflow composition |
| Display | text, webhook-config, schedule-info | Read-only information |
| MCP | mcp-dynamic-args | Dynamic argument mapping for MCP tools |
Sources: apps/sim/blocks/types.ts42-87 apps/sim/blocks/types.ts92-106
SubBlocks can be conditionally shown based on mode (basic/advanced/trigger) and field conditions:
Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx:782-818, apps/sim/blocks/types.ts239-259
The UI supports keyboard shortcuts for common operations, registered through a global command system.
| Shortcut | Action | Handler Location |
|---|---|---|
Cmd/Ctrl + K | Open search modal | workflow.tsx1052-1054 |
Cmd/Ctrl + C | Copy selected blocks | workflow.tsx1035-1054 |
Cmd/Ctrl + V | Paste blocks | workflow.tsx1055-1061 |
Cmd/Ctrl + Z | Undo | workflow.tsx1026-1028 |
Cmd/Ctrl + Shift + Z | Redo | workflow.tsx1029-1034 |
Shift + L | Auto-layout | workflow.tsx1022-1025 |
Delete / Backspace | Delete selected blocks | workflow.tsx1069-1082 |
Global commands can also be triggered from the command palette or sidebar buttons.
Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:1013-1108, apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx:423-477
The UI carefully manages server-side rendering to prevent hydration mismatches:
_hasHydrated flag prevents accessing persisted state until after mount sidebar.tsx82-86The hydration system progresses through distinct phases:
idle → metadata-loading → metadata-ready → state-loading → ready
↘ error
Sources: apps/sim/stores/workflows/registry/store.ts21-46 apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx:52-86
The UI implements several performance optimizations to handle large workflows:
React.memo to prevent re-renders when unrelated blocks changeuseCallback to prevent dependency changes use-node-utilities.ts17-59Stores use shallow equality checks to prevent unnecessary re-renders:
Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:276-302, apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx:346-369
Non-critical UI components are lazy-loaded:
lazy(() => import('.../chat')) workflow.tsx86-90lazy(() => import('.../oauth-required-modal')) workflow.tsx91-95Sources: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx:85-96
Refresh this wiki
This wiki was recently refreshed. Please wait 1 day to refresh again.