11 KiB
Frontend
apps/web/ — React web UI for managing initiatives, agents, and content.
Tech Stack
| Technology | Purpose |
|---|---|
| React 19 | UI framework |
| TanStack Router | File-based routing |
| tRPC React Query | Type-safe API client with caching |
| Tailwind CSS | Utility-first styling |
| shadcn/ui | Component library (button, card, dialog, dropdown, input, label, textarea, badge, sonner, tooltip) |
| Tiptap | Rich text editor (ProseMirror-based) |
| Lucide | Icon library |
| Geist Sans/Mono | Typography (variable fonts in public/fonts/) |
Design System (v2)
Theme spec: docs/wireframes/v2/theme.md
- Brand: Indigo (#6366F1) —
--primaryis indigo, not black - Dark mode: 3-state toggle (light/system/dark), persisted in
localStorage('cw-theme') - Status tokens: 6 semantic statuses (active/success/warning/error/neutral/urgent) with bg/fg/border/dot variants. Use
bg-status-{status}-bg,text-status-{status}-fg, etc. - Terminal tokens: Always-dark surface for agent output. Use
bg-terminal,text-terminal-fg, etc. - Diff tokens:
bg-diff-add-bg,text-diff-remove-fg, etc. - Shadows: 5-level system (xs-xl). Dark mode uses inset highlights + ambient glow.
- Transitions:
duration-fast,duration-normal,ease-default,ease-spring - Z-index: Named scale from
z-basetoz-tooltip - Radius: 6px base (down from 8px)
- Flash prevention: Inline
<script>inindex.htmlreads theme before paint
Status-to-Entity Mapping
Use mapEntityStatus(rawStatus) from StatusDot.tsx to convert raw entity statuses to semantic tokens. StatusDot and StatusBadge both use this automatically.
Path Alias
@/* maps to ./src/* (configured in tsconfig.app.json).
Routes
| Route | Component | Purpose |
|---|---|---|
/ |
routes/index.tsx |
Dashboard / initiative list |
/initiatives/$id |
routes/initiatives/$initiativeId.tsx |
Initiative detail (tabbed) |
/agents |
routes/agents.tsx |
Agent list with Output / Details tab panel |
/settings |
routes/settings/index.tsx |
Settings page |
Initiative Detail Tabs
The initiative detail page has three tabs managed via local state (not URL params):
- Content Tab — Page tree + Tiptap editor, proposal review
- Execution Tab — Pipeline visualization, phase management, task dispatch
- Review Tab — Pending proposals from agents
Component Inventory (74 components)
Core Components (src/components/)
| Component | Purpose |
|---|---|
InitiativeCard |
Initiative list card with activity indicator (dot + label + phase progress), overflow menu |
InitiativeHeader |
Initiative name, project badges, inline-editable execution mode & branch |
InitiativeContent |
Content tab with page tree + editor |
StatusDot |
Small colored dot using status tokens, with pulse animation |
StatusBadge |
Colored badge using status tokens |
TaskRow |
Task list item with status, priority, category |
QuestionForm |
Agent question form with options |
AgentDetailsPanel |
Details tab for agent right-panel: metadata, input files, effective prompt |
InboxDetailPanel |
Agent message detail + response form |
ProjectPicker |
Checkbox list for project selection |
RegisterProjectDialog |
Dialog to register new git project |
Skeleton |
Loading placeholder with shimmer animation |
SkeletonCard |
Composite skeleton layouts (agent-card, initiative-card, etc.) |
EmptyState |
Shared empty state with icon, title, description, action |
ErrorState |
Shared error state with retry |
SaveIndicator |
Saving/saved/error status indicator |
CommandPalette |
Cmd+K search palette (initiatives, agents, navigation) |
ThemeToggle |
3-state theme toggle (Sun/Monitor/Moon) |
NavBadge |
Numeric badge for nav items |
KeyboardShortcutHint |
Formatted keyboard shortcut display |
ConnectionBanner |
Offline/reconnecting state banner |
HealthDot |
Server health indicator with tooltip |
BrowserTitleUpdater |
Dynamic document.title with agent counts |
Editor Components (src/components/editor/)
| Component | Purpose |
|---|---|
TiptapEditor |
Core rich text editor wrapper |
PageEditor |
Page content editor with auto-save |
PhaseContentEditor |
Phase content editor |
ContentProposalReview |
Accept/dismiss proposals from agents |
SlashCommandMenu |
Slash command popup in editor |
Execution Components (src/components/execution/)
| Component | Purpose |
|---|---|
ExecutionTab |
Main execution view container |
ExecutionContext |
React context for execution state |
PhaseDetailPanel |
Phase detail with tasks, dependencies, plan |
PhaseSidebar |
Phase list sidebar |
TaskDetailPanel |
Task detail with agent status, output |
Pipeline Components (src/components/pipeline/)
| Component | Purpose |
|---|---|
PipelineTab |
Execution tab entry — fetches tasks, phase deps, task deps |
PipelineGraph |
Horizontal DAG of phase columns with connectors |
PipelineStageColumn |
Single depth column containing phase groups |
PipelinePhaseGroup |
Phase card with status border accent, progress bar, TaskGraph |
Review Components (src/components/review/)
| Component | Purpose |
|---|---|
ReviewTab |
Review tab container — orchestrates header, diff, sidebar, and preview. Phase-level review has threaded inline comments (with reply support) + Request Changes; initiative-level review has Request Changes (summary prompt) + Push Branch / Merge & Push |
ReviewHeader |
Consolidated toolbar: phase selector pills, branch info, stats, preview controls, approve/reject actions |
ReviewSidebar |
VSCode-style icon strip (Files/Commits views) with file list, root-only comment counts, and commit navigation |
DiffViewer |
Unified diff renderer with threaded inline comments (root + reply threads) |
CommentThread |
Renders root comment with resolve/reopen + nested reply threads (agent replies styled with primary border). Inline reply form |
ConflictResolutionPanel |
Merge conflict detection + agent resolution in initiative review. Shows conflict files, spawns conflict agent, inline questions, re-check on completion |
PreviewPanel |
Docker preview status: building/running/failed with start/stop (legacy, now integrated into ReviewHeader) |
ProposalCard |
Individual proposal display |
UI Primitives (src/components/ui/)
shadcn/ui components: badge (6 status variants + xs size), button, card, dialog, dropdown-menu, input, label, select, sonner, textarea, tooltip.
Custom Hooks (src/hooks/)
| Hook | Purpose |
|---|---|
useRefineAgent |
Manages refine agent lifecycle for initiative |
useConflictAgent |
Manages conflict resolution agent lifecycle for initiative review |
useDetailAgent |
Manages detail agent for phase planning |
useAgentOutput |
Subscribes to live agent output stream |
useChatSession |
Manages chat session for phase/task refinement |
useConnectionStatus |
Tracks online/offline/reconnecting state |
useGlobalKeyboard |
Global keyboard shortcuts (1-4 nav, Cmd+K) |
Theme (src/lib/theme.tsx)
ThemeProvider wraps the app root. useTheme() returns { theme, setTheme, isDark }. The provider listens for OS prefers-color-scheme changes when in system mode.
tRPC Client
Configured in src/lib/trpc.ts. Uses @trpc/react-query with TanStack Query for caching and optimistic updates.
Key User Flows
Creating an Initiative
- Dashboard → "New Initiative" → enter name, optional description, select projects
createInitiativemutation → auto-creates root page (seeded with description as tiptap content); if description provided, auto-spawns refine agent- Navigate to initiative detail page on success
Managing Content (Pages)
- Content tab → page tree sidebar
- Click page → Tiptap editor loads content
- Edit → auto-saves via
updatePagemutation - Use slash commands for formatting
Refining Content with AI
- Content tab → "Refine" button
spawnArchitectRefinemutation → agent analyzes pages- Agent creates proposals (page edits, new phases, tasks)
- Proposals appear in review section → accept/dismiss each
Pipeline Visualization
- Execution tab → pipeline DAG shows phases as nodes
- Drag to add dependencies between phases
- Per-phase Play button: if phase is
pending(with non-detail tasks), approves then queues in one click; if alreadyapproved, just queues - "Execute N phases" top-level button: approves all
pendingphases that have tasks, then callsqueueAllPhases— count includes bothpending(with tasks) andapprovedphases - Tasks auto-queued when phase starts
Detailing Phases
- Select phase → "Detail" button
spawnArchitectDetailmutation → agent creates task proposals- Accept proposals → tasks created under phase
- View tasks in phase detail panel
Chat with Phase/Task
- Execution tab → select phase → "Chat" button (or open task → "Chat" button in footer)
ChatSlideOveropens as right-side panel- Send message →
sendChatMessagemutation → agent spawns (or resumes) in'chat'mode - Agent applies changes (create/update/delete phases, tasks, pages) → changeset created
- Assistant message appears with inline changeset summary + revert button
- Send next message → agent resumes → repeat
- Close chat → session closed, agent dismissed
Components: ChatSlideOver, ChatBubble, ChatInput, ChangeSetInline in src/components/chat/.
Shared Package
packages/shared/ exports:
sortByPriorityAndQueueTime()— priority-based task sortingtopologicalSort()/groupByPipelineColumn()— phase DAG layoutInitiativeActivity/InitiativeActivityState— server-computed activity state for initiative cards- Shared type re-exports from
packages/shared/src/types.ts(which re-exports fromapps/server/)
Initiative Activity Indicator
listInitiatives returns an activity field on each initiative, computed server-side from phase statuses via deriveInitiativeActivity() in apps/server/trpc/routers/initiative-activity.ts. This eliminates per-card N+1 listPhases queries.
Activity states (priority order): conflict agent > archived > active architect agents > pending_review > executing > blocked > complete > ready > planning > idle. Each state maps to a StatusVariant + pulse animation in InitiativeCard's activityVisual() function. Active conflict agents (name starts with conflict-) are checked first — returning resolving_conflict (urgent variant, pulsing). Active architect agents (modes: discuss, plan, detail, refine) are checked next — mapping to discussing, detailing, detailing, refining states respectively — so auto-spawned agents surface activity even when no phases exist yet. PhaseSidebarItem also shows a spinner when a detail agent is active for its phase.