React Integration (@critical-path/react)
The @critical-path/react package provides ready-to-use hooks for tasks, projects, and Kanban boards.
Setup: Provider
Wrap your app or page subtree with CriticalPathProvider:
import { CriticalPathProvider } from '@critical-path/react';
export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <CriticalPathProvider options={{ baseUrl: '/api/critical-path' }}> {children} </CriticalPathProvider> );}Available Hooks
useTasks
Manages task retrieval, filtering, and CRUD operations with optimistic rollback:
import { useTasks } from '@critical-path/react';
function TaskView({ projectId }: { projectId: string }) { const { tasks, loading, error, createTask, updateTask, updateTaskStatus, deleteTask } = useTasks(projectId);
const handleUpdate = async (taskId: string) => { await updateTask(taskId, { priority: 'urgent' }); };
return (/* JSX */);}useProjects
Manages project listing and creation:
import { useProjects } from '@critical-path/react';
function ProjectSelector() { const { projects, loading, createProject } = useProjects(); return (/* JSX */);}useKanban
Organizes tasks into workflow or semantic Kanban columns with reordering and drag-and-drop support:
import { useKanban } from '@critical-path/react';
function KanbanBoard({ projectId }: { projectId: string }) { const { columns, moveTask, loading } = useKanban(projectId, { groupBy: 'workflow' });
if (loading) return <div>Loading board...</div>;
return ( <div className="flex gap-4"> {Object.entries(columns).map(([columnName, tasks]) => ( <div key={columnName} className="w-72 bg-gray-100 p-4 rounded"> <h3 className="font-bold">{columnName} ({tasks.length})</h3> {tasks.map(task => ( <div key={task.id} className="p-2 bg-white rounded shadow my-2"> <span>{task.title}</span> <button onClick={() => moveTask(task.id, 'done')}>Done</button> </div> ))} </div> ))} </div> );}useTaskActivity
Combines threaded discussions with inline attachments and emoji reactions:
import { useTaskActivity } from '@critical-path/react';
function TaskActivity({ taskId }: { taskId: string }) { const { threads, standaloneAttachments, addComment, addReaction } = useTaskActivity(taskId);
return ( <div> {threads.map(thread => ( <div key={thread.id}> <p>{thread.content}</p> <button onClick={() => addReaction(thread.id, '👍', 'user_1')}>👍</button> </div> ))} </div> );}useTaskTransitions
Fetches allowed state transitions for a task governed by workflow definitions:
import { useTaskTransitions } from '@critical-path/react';
function TaskStatusPicker({ taskId }: { taskId: string }) { const { allowedTransitions, loading } = useTaskTransitions(taskId);
return ( <select> {allowedTransitions.map(status => ( <option key={status} value={status}>{status}</option> ))} </select> );}useWebMCP
Registers client-side WebMCP tools into the browser context (document.modelContext) for AI copilots, automatically scoped to the active project:
import { useWebMCP } from '@critical-path/react';
function CopilotIntegration({ projectId }: { projectId: string }) { const { registered, tools, error } = useWebMCP({ projectId, tools: ['create_task', 'list_tasks', 'update_task', 'add_comment'] });
if (!registered) return null;
return ( <div className="copilot-badge"> 🤖 AI Assistant Active ({tools.length} actions available) </div> );}