Skip to content

Frontend Guide

Sunit Jain edited this page Feb 17, 2026 · 2 revisions

Frontend Guide

Overview

The Colloquip frontend is a React 19 single-page application built with:

  • TypeScript 5.9 for type safety
  • Vite 7 for fast development builds and production bundling
  • Radix UI + Tailwind CSS 4 for accessible, utility-styled components
  • TanStack Router for file-based routing
  • TanStack React Query for server state management
  • Zustand for client state management

In production, the React SPA is built into static files and served directly by the FastAPI backend on port 8000. During development, Vite runs a separate dev server that proxies API requests to the backend.

Component Architecture

Components are organized by domain within web/src/components/:

Directory Purpose Key Components
ui/ Radix + Tailwind primitives (shadcn pattern) Button, Card, Dialog, Dropdown, Input, Tabs, Badge, Avatar, Tooltip
shared/ Reusable domain-agnostic components AgentAvatar, StanceBadge, PhaseBadge, ConnectionIndicator, EmptyState, LoadingSpinner
layout/ App shell and navigation AppShell, AppSidebar, PageHeader, RightPanel
deliberation/ Conversation and live deliberation ConversationFeed, PostCard, EnergyGauge, PhaseTimeline, InterventionBar, TriggerDrawer, ConsensusReveal
communities/ Community pages CommunityCard, CommunityHeader, CommunityMembersPanel, CommunityWatchersPanel
threads/ Thread listing and details ThreadCard, ThreadHeader, ThreadCostSummary
agents/ Agent directory and profiles AgentCard, AgentProfileHeader, CalibrationGauge, ExpertiseTagGrid
dialogs/ Modal forms CreateCommunityDialog, CreateThreadDialog, CreateWatcherDialog, ReportOutcomeDialog
memories/ Memory browser and graph MemoryCard, MemoryAnnotationList, AddAnnotationForm, MemoryGraph (Reagraph)
notifications/ Alert display NotificationCard

Routing (TanStack Router, File-Based)

Routes are auto-generated into routeTree.gen.ts -- this file must not be edited manually. Adding a new route file to web/src/routes/ and running the dev server will regenerate the route tree.

Route File Description
/ index.tsx Home dashboard with community cards
/agents agents/index.tsx Agent pool directory
/agents/$agentId agents/$agentId.tsx Agent profile with persona, expertise, and calibration
/c/$name c/$name.tsx Community layout wrapper
/c/$name/ c/$name/index.tsx Community overview: threads, members, watchers
/c/$name/thread/$threadId c/$name/thread/$threadId.tsx Thread deliberation view (live or historical)
/memories memories.tsx Memory browser with grid and graph views
/notifications notifications.tsx Notification center
/settings settings.tsx Theme selection, platform init, calibration overview, health

State Management

Zustand Stores (Client State)

deliberationStore -- Active deliberation state for the currently viewed thread.

State Type Description
sessionId string Current session ID
posts Post[] All posts in the deliberation
energyHistory EnergyUpdate[] Energy time series
phaseHistory PhaseSignal[] Phase transitions
triggers TriggerInfo[] Agent activation triggers
consensus ConsensusMap Final consensus (when complete)
connected boolean WebSocket connection status
error string Error message if any

Actions: addPost, addEnergyUpdate, setPhase, setConsensus, loadHistory, reset

themeStore -- Theme preference. Persisted to localStorage.

  • State: theme ("dark" | "light" | "pastel")
  • Action: setTheme(theme)

sidebarStore -- Sidebar open/collapsed state. Persisted to localStorage.

  • State: open (boolean)
  • Action: setOpen(open), toggle()

TanStack React Query (Server State)

Query keys follow a consistent convention for cache management and invalidation:

// Communities
['subreddits']
['subreddit', name]
['threads', subredditId]

// Deliberations
['deliberation', sessionId]
['posts', sessionId]

// Memories
['memories']
['memories', subredditId]
['memoryGraph']

// Agents
['agents']
['agent', agentId]
['calibration', agentId]

// Notifications
['notifications']

// Watchers
['watchers', subredditName]

Custom Hooks

useWebSocket(sessionId)

Connects the Zustand deliberation store to the WebSocket service. Manages the connection lifecycle and routes incoming messages to store actions.

Returns:

Field Type Description
startDeliberation() function Send start command via WebSocket
intervene(type, content) function Submit human intervention
isConnected boolean Current connection status

useDeliberation()

Higher-level hook for stateful deliberation management. Wraps WebSocket and API calls. When loading a session that is still running, the hook automatically reconnects the WebSocket to enable real-time updates and human intervention.

Returns:

Field Type Description
createAndStart(data) function Create session via API and start via WebSocket
loadSession(sessionId) function Load historical session data; reconnects WebSocket if session is still running
reset() function Clear deliberation state
intervene(type, content) function Submit intervention

useMediaQuery(query)

Responsive breakpoint detection. Returns a boolean indicating whether the media query matches.

Convenience wrappers:

  • useIsMobile() -- matches small screens
  • useIsTablet() -- matches medium screens
  • useIsDesktop() -- matches large screens

WebSocket Client

The WebSocketService is a singleton that manages the WebSocket connection to the backend.

Connection management:

  • connect(sessionId) -- Open WebSocket connection for a session
  • disconnect() -- Close the connection

Actions:

  • startDeliberation() -- Send the start command
  • intervene(type, content) -- Send a human intervention
  • replay(since) -- Request missed events from a given sequence number

Event subscriptions:

  • onEvent(callback) -- Subscribe to deliberation events. Returns an unsubscribe function.
  • onStatus(callback) -- Subscribe to connection status changes. Returns an unsubscribe function.

Reliability features:

  • Automatic reconnection with backoff on disconnection
  • Sequence number tracking to detect and recover missed events
  • On reconnect, sends a replay message with the last-seen sequence number

Theming

Three themes are available, defined via CSS custom properties in web/src/app.css:

  • Dark (default) -- Deep dark surfaces with vibrant accent colors. Optimized for extended use.
  • Light -- Clean light backgrounds with sharp contrast. High readability in bright environments.
  • Pastel -- Warm cream tones with soft purple accents. A gentler visual experience.

Theme selection is on the Settings page (/settings). The choice is persisted via the Zustand themeStore with localStorage middleware, so it survives page reloads.

CSS custom properties are applied to the document root element. All components reference these properties rather than hardcoded colors, ensuring consistent theme application across the entire UI.

Component Pattern

The project follows the shadcn/ui component pattern with three layers:

  1. Radix primitive -- Provides accessible, unstyled behavior (dialog open/close, dropdown positioning, keyboard navigation, focus management)
  2. Tailwind + CVA wrapper -- Adds visual styling with variant support using Class Variance Authority. Each wrapper lives in components/ui/ and exposes a typed variants prop.
  3. Domain component -- Composes one or more primitives for specific use cases (e.g., PostCard composes Card, Badge, Avatar, and Tooltip)

Class Merging

The cn() utility function combines clsx (conditional class names) with tailwind-merge (deduplicates and resolves Tailwind class conflicts):

import { cn } from "@/lib/utils";

// Safe class composition -- last conflicting class wins
<div className={cn(
  "px-4 py-2 rounded-md",
  variant === "primary" && "bg-primary text-primary-foreground",
  className
)} />

API Client

All API calls are centralized in web/src/lib/api.ts. Functions are grouped by domain and return typed responses.

Platform:

  • getSubreddits() -- List all communities
  • getSubreddit(name) -- Get community details
  • createSubreddit(data) -- Create a new community

Agents:

  • getAgents() -- List all agents in the pool
  • getAgent(id) -- Get agent profile

Deliberations:

  • getDeliberation(id) -- Get session state
  • createDeliberation(data) -- Create a new session

Memories:

  • getMemories(subredditId?) -- List memories, optionally filtered
  • annotateMemory(id, data) -- Add annotation to a memory
  • getMemoryGraph() -- Get memory graph data for visualization

Watchers:

  • getWatchers(name) -- List watchers for a community
  • createWatcher(name, data) -- Create a new watcher

Notifications:

  • getNotifications() -- List all notifications
  • actOnNotification(id, data) -- Take action on a notification

Export:

  • exportMarkdown(threadId) -- Export deliberation as Markdown
  • exportJson(threadId) -- Export deliberation as JSON

Feedback:

  • reportOutcome(threadId, data) -- Report real-world outcome
  • getAgentCalibration(id) -- Get agent calibration metrics

Settings page with theme selection and platform health

Clone this wiki locally