Canvases and widgets
Every workspace mode is a React Flow canvas you can extend with draggable widgets.
Project88's UI is canvas-first. Every workspace mode — Home, Chat, Data,
Agents, Office, and so on — is rendered inside a blank, infinite React Flow
board (CanvasBlankCard). You can add widgets to it: draggable,
resizable nodes that surface live workspace data.
Canvases
Each canvas is identified by a (org_id, type, slug) tuple and persisted
to the canvases table:
type—boardfor user-created canvases;orchestration,agent_pipeline,agent_configfor system canvases.slug— the workspace mode (home,chat,data,agents,office, etc.) or a user-chosen name.nodes/edges— the React Flow graph as JSONB.metadata— anchor viewport, name, icon, description, read-only flag.
Nodes and edges auto-save with an 800 ms debounce. Reopening a canvas restores the exact layout — including the saved zoom and viewport position via the anchor viewport (right-click → Canvas Settings → Set Anchor).
Editing
Canvases are read-only by default. Toggle edit mode from the canvas settings popup. In edit mode:
- Right-click a free spot → Add Widget → category → Small / Medium / Large size.
- Right-click an existing node → settings panel (background, border, shape, opacity, shadow, typography, handle configuration).
- Drag to move. The NodeResizer lets you resize.
- Keyboard shortcuts:
⌘Zundo,⌘⇧Zredo,⌘Dduplicate,⌘C/Vcopy/paste,Delete,⌘Aselect all,Escapedeselect. - Undo/redo keeps a snapshot history of up to 50 steps, including drag positions.
Widgets
A widget is a node that wraps a small interactive React app. Each widget ships in three sizes:
| Size | What you get |
|---|---|
| Small | Icon-only — quick visual indicator |
| Medium | Compact preview (mini-table, mini-form) |
| Large | Full interactive view |
Built-in widgets — chat, data, pages:
- NewChatWidget — chat input with model + agent selector and recents
- DataTableWidget — interactive table view
- DataTableListWidget — list of all tables; outputs
tableId - DataTableViewerWidget — paginated view; outputs
selectedRowId - DataRecordWidget — single-record card with prev/next nav
- DataStatsWidget — KPI cards (row count, fill %, latest update)
- PagesWidget — recents list + full block-aware page viewer
Built-in widgets — calendar, tasks, pipeline:
- CalendarWeekWidget — week grid with drag-to-reschedule and drag-across-calendars
- CalendarMonthWidget — month grid
- CalendarAgendaWidget — agenda list with Now / Next status and per-event tag color
- TasksWidget — pull
kind = 'task'activities into a checklist; groups by overdue / due today / upcoming - PipelineStageWidget — kanban stages over records, conversations, events, or any taggable entity; rule-based filters
Built-in widgets — agent builder and dial:
- AgentBuilderWidget — full agent editor on the canvas, with eight tabs (General, Prompt, Variables, Examples, Tools, Identity, Sandbox, Sub-agents)
- DialWidget, DialBucketListWidget, DialStatsWidget, plus the supporting panels — see Dial mode
Connecting widgets
Widgets declare a DATA_ROLE:
source— outputs data (e.g.DataTableListWidgetoutputstableId).both— accepts upstream input and emits output (e.g.DataTableWidgettakes atableIdand emits aselectedRowId).target— consumes upstream input only (e.g.DataRecordWidget,DataStatsWidget).
When you connect a source/both widget to a both/target widget, two values flow:
data.upstreamTableId— propagates downstream so the connected widget knows which table to render.data.upstreamRowId— emitted when you click a row in a table widget; downstream record widgets re-render to that row.
Connected widgets show a small ● Linked / ● Row Linked indicator. Disconnecting clears the upstream and restores manual selectors.
Handles
Each enabled handle is exactly one type:
- Source nodes — all handles blue (outgoing).
- Target nodes — all handles green (incoming).
- Both nodes — left handles green (targets), right handles blue (sources).
The settings panel handle picker shows colored dots matching the resolved
type. connectionMode="strict" ensures source→target only.
isValidConnection blocks self-connections and anchor edges.
The Office and Planning canvases
Two specialised canvases:
- Office — read-only bird's-eye view of every agent in the workspace, with delegation edges between them. Clicking an agent opens its AgentCanvasModal.
- Planning — text-centric canvas attached to a page, with Text, Task, Group, and Link nodes. Renders as an inline preview above the page blocks.
Both share the same EditorShell and FlowNodeShell infrastructure as the
Automation editor.
The Pipeline Stage widget
Worth calling out: the PipelineStageWidget is a kanban-style stage
widget that groups entities by stage. Stages are derived from tags or a
column value, and rules decide which entity belongs to which stage —
tag match, date range, numeric comparison, text match. Drag an entity
between stages to retag it.
Use it for sales pipelines (records → stages by opportunity status), support boards (conversations → stages by priority tag), or any kanban-shaped workflow over your data.
Widget linking primitive
A newer primitive (src/widgetLinks/) lets one widget's selection drive
another's filter — wire the Email Inbox widget to a Records widget
so clicking an email opens the linked customer record, for example. Links
are configured per pair of widgets and persist with the canvas.
Where to go next
- Home mode
- Workflow basics — the Automation editor (same canvas tech, different node palette).
- Office mode