Claude-skill-registry coeditor
Build React applications with CopilotKit and LangGraph for AI-powered collaborative editing. Creates production-ready editor applications (text, document, or node-based) with real-time AI assistance, shared state management, and agentic workflows. Use this skill when users want to build intelligent editing interfaces with AI collaboration features.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/coeditor" ~/.claude/skills/majiayu000-claude-skill-registry-coeditor && rm -rf "$T"
skills/data/coeditor/SKILL.mdCopilotKit + LangGraph Collaborative Editor Builder
Build production-ready React applications that combine CopilotKit's AI copilot interface with LangGraph's agentic workflows for intelligent, collaborative editing experiences.
When to Use This Skill
Use this skill when:
- User wants to build an AI-powered editor (text, document, or node-based)
- User mentions "CopilotKit", "LangGraph", "AI copilot", or "collaborative editing"
- User wants to add AI assistance to an existing React application
- User needs real-time state sharing between UI and AI agents
- User wants to build document collaboration features with AI
- User mentions "agentic workflows" or "multi-agent systems" in editing context
Overview
This skill scaffolds applications that combine:
- CopilotKit: React components for AI copilot experiences (chat, suggestions, actions)
- LangGraph: Agent orchestration framework for complex workflows
- React State Management: Shared state between editor UI and AI agents
- Editor Types: Text editors, document editors, or node-based editors
Prerequisites Check
Before starting, verify the following:
-
Node.js: Version 18.x or higher
node --version -
Package Manager: npm, yarn, or pnpm
npm --version -
Python: Version 3.9 or higher (for LangGraph backend)
python3 --version -
OpenAI API Key (or other LLM provider):
# Will need to be configured in .env echo "User will need OpenAI API key or alternative LLM provider"
Interactive Requirements Gathering
IMPORTANT: Before scaffolding, ask the user these questions to customize the setup:
1. Editor Type Selection
"What type of editor would you like to build?"
A. Text Editor
- Rich text editing with AI assistance
- Code editor with autocomplete and suggestions
- Markdown editor with AI enhancements
- Best for: Writing tools, code editors, note-taking apps
B. Document Editor
- Structured document editing (like Google Docs)
- Multi-section documents with AI collaboration
- Template-based document creation
- Best for: Documentation tools, report builders, collaborative writing
C. Node-Based Editor
- Visual graph/flow editor with AI assistance
- Workflow builders with intelligent suggestions
- Mind mapping with AI expansion
- Best for: Workflow designers, visual programming tools, diagramming apps
2. LangGraph Agent Configuration
"What type of AI agents do you need?"
Ask the user to describe their use case, then suggest appropriate agents:
Common Agent Types:
- Writing Assistant: Helps with content creation, editing, and refinement
- Code Assistant: Provides code suggestions, explanations, and debugging
- Research Agent: Searches and incorporates external information
- Reviewer Agent: Reviews content and provides feedback
- Summarizer Agent: Creates summaries and extracts key points
- Translator Agent: Translates between languages
- Custom Agents: User-defined specialized agents
Multi-Agent Workflows:
- Ask if they need multiple agents working together
- Determine if agents should run sequentially or in parallel
- Identify handoff points between agents
3. State Management Requirements
"What data needs to be shared between the editor and AI agents?"
Common State Patterns:
- Document State: Content, structure, metadata
- Selection State: Current cursor position, selected text/nodes
- History State: Undo/redo, version tracking
- Collaboration State: Multi-user presence, changes
- Agent State: Current agent task, progress, results
4. Backend Architecture
"How would you like to deploy the LangGraph backend?"
A. Local Development Server
- FastAPI server running locally
- Best for: Development, prototyping
- Setup: Python virtual environment
B. Cloud Deployment
- Deploy to Vercel, Railway, or cloud provider
- Best for: Production, sharing with team
- Setup: Containerized deployment
C. Serverless Functions
- Deploy agents as serverless functions
- Best for: Cost-effective scaling
- Setup: Vercel Functions, AWS Lambda
5. Additional Features
Ask about optional features:
CopilotKit Features:
- Chat interface (CopilotChat)
- Inline suggestions (CopilotTextarea)
- Custom actions (CopilotAction)
- Context providers (document context)
- Keyboard shortcuts
Editor Features:
- Real-time collaboration
- Version history
- Comments and annotations
- Export formats (PDF, Markdown, etc.)
- Templates
- Search and replace
AI Features:
- Streaming responses
- Multi-turn conversations
- Agent memory/context
- Custom prompts/instructions
- Fine-tuned models
Project Structure
Based on user selections, create this structure:
<app-name>/ ├── frontend/ # React application │ ├── src/ │ │ ├── components/ │ │ │ ├── Editor/ # Editor components │ │ │ │ ├── TextEditor.tsx │ │ │ │ ├── DocumentEditor.tsx │ │ │ │ └── NodeEditor.tsx │ │ │ ├── Copilot/ # CopilotKit components │ │ │ │ ├── CopilotProvider.tsx │ │ │ │ ├── ChatPanel.tsx │ │ │ │ └── Actions.tsx │ │ │ └── shared/ # Shared UI components │ │ ├── hooks/ # Custom React hooks │ │ │ ├── useEditor.ts │ │ │ ├── useAgents.ts │ │ │ └── useSharedState.ts │ │ ├── state/ # State management │ │ │ ├── editorStore.ts │ │ │ ├── agentStore.ts │ │ │ └── types.ts │ │ ├── lib/ # Utilities │ │ │ ├── copilot-config.ts │ │ │ └── api-client.ts │ │ ├── App.tsx │ │ └── main.tsx │ ├── package.json │ ├── vite.config.ts │ └── tsconfig.json │ ├── backend/ # LangGraph backend │ ├── agents/ # Agent definitions │ │ ├── __init__.py │ │ ├── writing_assistant.py │ │ ├── code_assistant.py │ │ └── custom_agents.py │ ├── graphs/ # LangGraph workflows │ │ ├── __init__.py │ │ ├── editor_graph.py │ │ └── multi_agent_graph.py │ ├── api/ # FastAPI endpoints │ │ ├── __init__.py │ │ ├── main.py │ │ └── routes.py │ ├── state/ # Shared state management │ │ ├── __init__.py │ │ └── state_manager.py │ ├── requirements.txt │ └── pyproject.toml │ ├── shared/ # Shared types/schemas │ ├── types.ts │ └── schemas.py │ ├── .env.example ├── .gitignore ├── docker-compose.yml # Optional: for containerized dev ├── README.md └── package.json # Root workspace config
Step-by-Step Implementation
Step 1: Project Initialization
1.1 Create React Frontend (Vite + TypeScript)
npm create vite@latest <app-name> -- --template react-ts cd <app-name> mv <app-name> frontend
1.2 Install CopilotKit Dependencies
cd frontend npm install @copilotkit/react-core @copilotkit/react-ui @copilotkit/react-textarea
1.3 Install Editor Dependencies
Choose based on editor type:
For Text/Code Editor:
npm install @monaco-editor/react # VS Code editor # OR npm install @tiptap/react @tiptap/starter-kit # Rich text
For Document Editor:
npm install slate slate-react # Document framework # OR npm install @lexical/react lexical # Facebook's editor framework
For Node-Based Editor:
npm install reactflow # Flow/graph editor # OR npm install @xyflow/react # Advanced node editor
1.4 Install State Management
npm install zustand # Lightweight state management # OR npm install @tanstack/react-query # Server state management # OR npm install jotai # Atomic state management
1.5 Initialize Python Backend
cd .. mkdir backend cd backend python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
1.6 Install LangGraph Dependencies
pip install langgraph langchain langchain-openai fastapi uvicorn python-dotenv pydantic websockets
Create
requirements.txt:
pip freeze > requirements.txt
Step 2: Configure CopilotKit
2.1 Create CopilotKit Provider (
)frontend/src/components/Copilot/CopilotProvider.tsx
import { CopilotKit } from "@copilotkit/react-core"; import { CopilotSidebar } from "@copilotkit/react-ui"; import "@copilotkit/react-ui/styles.css"; interface CopilotProviderProps { children: React.ReactNode; } export function CopilotProvider({ children }: CopilotProviderProps) { return ( <CopilotKit runtimeUrl="/api/copilotkit" // Alternatively, connect directly to LangGraph backend: // runtimeUrl="http://localhost:8000/copilot" > <CopilotSidebar> {children} </CopilotSidebar> </CopilotKit> ); }
2.2 Configure Context Providers
CopilotKit needs access to editor state to provide relevant suggestions:
import { useCopilotReadable, useCopilotAction } from "@copilotkit/react-core"; export function useEditorCopilot(editorState: EditorState) { // Make editor state readable by AI useCopilotReadable({ description: "The current document content and structure", value: editorState, }); // Define actions AI can perform useCopilotAction({ name: "insertText", description: "Insert text at current cursor position", parameters: [ { name: "text", type: "string", description: "The text to insert", required: true, }, ], handler: async ({ text }) => { // Insert text into editor editorState.insertText(text); }, }); useCopilotAction({ name: "replaceSelection", description: "Replace currently selected text", parameters: [ { name: "newText", type: "string", description: "The replacement text", required: true, }, ], handler: async ({ newText }) => { editorState.replaceSelection(newText); }, }); }
Step 3: Set Up LangGraph Backend
3.1 Define State Schema (
)backend/state/state_manager.py
from typing import TypedDict, Annotated, Sequence from langchain_core.messages import BaseMessage import operator class EditorState(TypedDict): """Shared state between frontend and agents.""" # Document content content: str # Current selection selection: dict # Chat messages messages: Annotated[Sequence[BaseMessage], operator.add] # Agent context current_agent: str # Task tracking task_status: str # Additional metadata metadata: dict
3.2 Create Base Agent (
)backend/agents/base_agent.py
from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnablePassthrough class BaseAgent: def __init__(self, name: str, system_prompt: str): self.name = name self.llm = ChatOpenAI(model="gpt-4", temperature=0.7) self.prompt = ChatPromptTemplate.from_messages([ ("system", system_prompt), ("human", "{input}"), ]) self.chain = self.prompt | self.llm async def process(self, state: EditorState) -> EditorState: """Process state and return updated state.""" raise NotImplementedError
3.3 Implement Specific Agents
Based on user requirements, create specialized agents:
Writing Assistant (
)backend/agents/writing_assistant.py
from .base_agent import BaseAgent from ..state.state_manager import EditorState class WritingAssistant(BaseAgent): def __init__(self): super().__init__( name="writing_assistant", system_prompt="""You are an expert writing assistant. Help users improve their writing by: - Suggesting better phrasing - Fixing grammar and style issues - Expanding on ideas - Maintaining consistent tone Current document context: {content} Current selection: {selection} """ ) async def process(self, state: EditorState) -> EditorState: # Get current content and selection content = state.get("content", "") selection = state.get("selection", {}) # Process with LLM result = await self.chain.ainvoke({ "input": state["messages"][-1].content, "content": content, "selection": selection, }) # Update state state["messages"].append(result) state["task_status"] = "completed" return state
Code Assistant (
)backend/agents/code_assistant.py
from .base_agent import BaseAgent from ..state.state_manager import EditorState class CodeAssistant(BaseAgent): def __init__(self): super().__init__( name="code_assistant", system_prompt="""You are an expert programming assistant. Help users with: - Code completion and suggestions - Bug finding and fixing - Code explanation - Refactoring suggestions Current code: {content} Selected code: {selection} """ ) async def process(self, state: EditorState) -> EditorState: content = state.get("content", "") selection = state.get("selection", {}) result = await self.chain.ainvoke({ "input": state["messages"][-1].content, "content": content, "selection": selection, }) state["messages"].append(result) return state
3.4 Create LangGraph Workflow (
)backend/graphs/editor_graph.py
from langgraph.graph import StateGraph, END from ..state.state_manager import EditorState from ..agents.writing_assistant import WritingAssistant from ..agents.code_assistant import CodeAssistant def create_editor_graph(): """Create LangGraph workflow for editor agents.""" # Initialize agents writing_agent = WritingAssistant() code_agent = CodeAssistant() # Create graph workflow = StateGraph(EditorState) # Add nodes workflow.add_node("writing_assistant", writing_agent.process) workflow.add_node("code_assistant", code_agent.process) # Add conditional routing def route_agent(state: EditorState) -> str: """Route to appropriate agent based on state.""" current_agent = state.get("current_agent", "writing_assistant") return current_agent # Set entry point workflow.set_conditional_entry_point( route_agent, { "writing_assistant": "writing_assistant", "code_assistant": "code_assistant", } ) # Add edges workflow.add_edge("writing_assistant", END) workflow.add_edge("code_assistant", END) return workflow.compile()
3.5 Create FastAPI Server (
)backend/api/main.py
from fastapi import FastAPI, WebSocket from fastapi.middleware.cors import CORSMiddleware from ..graphs.editor_graph import create_editor_graph from ..state.state_manager import EditorState import json app = FastAPI() # CORS configuration app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:5173"], # Vite dev server allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Initialize graph graph = create_editor_graph() @app.post("/copilot") async def copilot_endpoint(request: dict): """CopilotKit-compatible endpoint.""" # Extract state from request state: EditorState = { "content": request.get("context", {}).get("content", ""), "selection": request.get("context", {}).get("selection", {}), "messages": request.get("messages", []), "current_agent": request.get("agent", "writing_assistant"), "task_status": "pending", "metadata": {}, } # Process through graph result = await graph.ainvoke(state) # Return response return { "message": result["messages"][-1].content, "state": result, } @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): """WebSocket for real-time updates.""" await websocket.accept() try: while True: # Receive state update from frontend data = await websocket.receive_text() state = json.loads(data) # Process through graph result = await graph.ainvoke(state) # Send back to frontend await websocket.send_json(result) except Exception as e: print(f"WebSocket error: {e}") finally: await websocket.close() if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)
Step 4: Implement Editor Component
Based on editor type, create the appropriate component:
4.1 Text Editor (Monaco/VS Code)
// frontend/src/components/Editor/TextEditor.tsx import Editor from '@monaco-editor/react'; import { useEditorStore } from '../../state/editorStore'; import { useEditorCopilot } from '../../hooks/useEditorCopilot'; export function TextEditor() { const { content, updateContent, selection } = useEditorStore(); // Connect to CopilotKit useEditorCopilot({ content, selection }); return ( <Editor height="90vh" defaultLanguage="typescript" value={content} onChange={(value) => updateContent(value || '')} onCursorSelectionChange={(selection) => { useEditorStore.setState({ selection }); }} theme="vs-dark" options={{ minimap: { enabled: true }, fontSize: 14, wordWrap: 'on', }} /> ); }
4.2 Document Editor (Slate)
// frontend/src/components/Editor/DocumentEditor.tsx import { createEditor } from 'slate'; import { Slate, Editable, withReact } from 'slate-react'; import { useState, useMemo } from 'react'; import { useEditorCopilot } from '../../hooks/useEditorCopilot'; export function DocumentEditor() { const editor = useMemo(() => withReact(createEditor()), []); const [value, setValue] = useState(initialValue); // Connect to CopilotKit useEditorCopilot({ content: JSON.stringify(value) }); return ( <Slate editor={editor} value={value} onChange={setValue}> <Editable placeholder="Start writing..." renderLeaf={renderLeaf} renderElement={renderElement} /> </Slate> ); }
4.3 Node-Based Editor (ReactFlow)
// frontend/src/components/Editor/NodeEditor.tsx import ReactFlow, { MiniMap, Controls, Background, useNodesState, useEdgesState, } from 'reactflow'; import 'reactflow/dist/style.css'; import { useEditorCopilot } from '../../hooks/useEditorCopilot'; export function NodeEditor() { const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); // Connect to CopilotKit useEditorCopilot({ content: JSON.stringify({ nodes, edges }), selection: selectedNodes, }); return ( <div style={{ width: '100vw', height: '100vh' }}> <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} fitView > <Controls /> <MiniMap /> <Background variant="dots" gap={12} size={1} /> </ReactFlow> </div> ); }
Step 5: State Management
5.1 Create Editor Store (Zustand)
// frontend/src/state/editorStore.ts import { create } from 'zustand'; interface EditorState { content: string; selection: { start: number; end: number; text: string; }; history: string[]; currentAgent: string; // Actions updateContent: (content: string) => void; updateSelection: (selection: EditorState['selection']) => void; setAgent: (agent: string) => void; undo: () => void; redo: () => void; } export const useEditorStore = create<EditorState>((set, get) => ({ content: '', selection: { start: 0, end: 0, text: '' }, history: [], currentAgent: 'writing_assistant', updateContent: (content) => set((state) => ({ content, history: [...state.history, state.content], })), updateSelection: (selection) => set({ selection }), setAgent: (agent) => set({ currentAgent: agent }), undo: () => { const { history } = get(); if (history.length > 0) { set({ content: history[history.length - 1], history: history.slice(0, -1), }); } }, redo: () => { // Implement redo logic }, }));
5.2 Create Agent Store
// frontend/src/state/agentStore.ts import { create } from 'zustand'; interface Agent { id: string; name: string; description: string; status: 'idle' | 'working' | 'completed' | 'error'; } interface AgentState { agents: Agent[]; activeAgent: string | null; taskQueue: Task[]; // Actions setActiveAgent: (agentId: string) => void; updateAgentStatus: (agentId: string, status: Agent['status']) => void; addTask: (task: Task) => void; } export const useAgentStore = create<AgentState>((set) => ({ agents: [ { id: 'writing_assistant', name: 'Writing Assistant', description: 'Helps with writing and editing', status: 'idle', }, { id: 'code_assistant', name: 'Code Assistant', description: 'Helps with coding and debugging', status: 'idle', }, ], activeAgent: null, taskQueue: [], setActiveAgent: (agentId) => set({ activeAgent: agentId }), updateAgentStatus: (agentId, status) => set((state) => ({ agents: state.agents.map((agent) => agent.id === agentId ? { ...agent, status } : agent ), })), addTask: (task) => set((state) => ({ taskQueue: [...state.taskQueue, task], })), }));
Step 6: Connect Frontend to Backend
6.1 Create API Client (
)frontend/src/lib/api-client.ts
interface CopilotRequest { context: { content: string; selection: any; }; messages: any[]; agent: string; } export class AgentAPIClient { private baseUrl: string; constructor(baseUrl: string = 'http://localhost:8000') { this.baseUrl = baseUrl; } async sendMessage(request: CopilotRequest) { const response = await fetch(`${this.baseUrl}/copilot`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(request), }); if (!response.ok) { throw new Error(`API error: ${response.statusText}`); } return response.json(); } // WebSocket connection for real-time updates connectWebSocket(onMessage: (data: any) => void) { const ws = new WebSocket(`ws://localhost:8000/ws`); ws.onmessage = (event) => { const data = JSON.parse(event.data); onMessage(data); }; return ws; } }
6.2 Create Custom Hook (
)frontend/src/hooks/useAgents.ts
import { useEffect, useState } from 'react'; import { AgentAPIClient } from '../lib/api-client'; import { useEditorStore } from '../state/editorStore'; import { useAgentStore } from '../state/agentStore'; export function useAgents() { const [client] = useState(() => new AgentAPIClient()); const { content, selection, currentAgent } = useEditorStore(); const { updateAgentStatus } = useAgentStore(); const sendToAgent = async (message: string) => { updateAgentStatus(currentAgent, 'working'); try { const response = await client.sendMessage({ context: { content, selection }, messages: [{ role: 'user', content: message }], agent: currentAgent, }); updateAgentStatus(currentAgent, 'completed'); return response; } catch (error) { updateAgentStatus(currentAgent, 'error'); throw error; } }; return { sendToAgent }; }
Step 7: Configuration Files
7.1 Environment Variables
Create
.env.example:
# Frontend VITE_API_URL=http://localhost:8000 # Backend OPENAI_API_KEY=your-api-key-here ANTHROPIC_API_KEY=optional-claude-key LANGCHAIN_API_KEY=optional-langsmith-key LANGCHAIN_TRACING_V2=true LANGCHAIN_PROJECT=coeditor-project
7.2 Docker Compose (Optional)
# docker-compose.yml version: '3.8' services: frontend: build: ./frontend ports: - "5173:5173" environment: - VITE_API_URL=http://backend:8000 depends_on: - backend backend: build: ./backend ports: - "8000:8000" environment: - OPENAI_API_KEY=${OPENAI_API_KEY} volumes: - ./backend:/app
Step 8: Development Scripts
8.1 Root Package.json
{ "name": "coeditor-app", "private": true, "workspaces": ["frontend", "backend"], "scripts": { "dev": "concurrently \"npm run dev:frontend\" \"npm run dev:backend\"", "dev:frontend": "cd frontend && npm run dev", "dev:backend": "cd backend && python -m uvicorn api.main:app --reload", "build": "npm run build:frontend", "build:frontend": "cd frontend && npm run build", "type-check": "cd frontend && npm run type-check" }, "devDependencies": { "concurrently": "^8.2.0" } }
Advanced Patterns
Multi-Agent Workflows
For complex tasks requiring multiple agents:
# backend/graphs/multi_agent_graph.py from langgraph.graph import StateGraph, END def create_multi_agent_workflow(): workflow = StateGraph(EditorState) # Add multiple agents workflow.add_node("researcher", researcher_agent.process) workflow.add_node("writer", writer_agent.process) workflow.add_node("reviewer", reviewer_agent.process) # Create workflow: research → write → review workflow.set_entry_point("researcher") workflow.add_edge("researcher", "writer") workflow.add_edge("writer", "reviewer") # Conditional loop back for revisions workflow.add_conditional_edges( "reviewer", should_revise, { "revise": "writer", "approve": END, } ) return workflow.compile()
Streaming Responses
For better UX with long-running tasks:
// Frontend streaming async function* streamAgentResponse(message: string) { const response = await fetch('/api/copilot/stream', { method: 'POST', body: JSON.stringify({ message }), }); const reader = response.body?.getReader(); const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); yield chunk; } }
Context-Aware Actions
Make agents aware of editor context:
useCopilotAction({ name: "improveSelection", description: "Improve the currently selected text", handler: async () => { const { selection } = useEditorStore.getState(); const improved = await sendToAgent( `Improve this text: ${selection.text}` ); replaceSelection(improved); }, });
Testing
Frontend Tests
// frontend/src/components/Editor/__tests__/TextEditor.test.tsx import { render, screen } from '@testing-library/react'; import { TextEditor } from '../TextEditor'; describe('TextEditor', () => { it('renders editor', () => { render(<TextEditor />); expect(screen.getByRole('textbox')).toBeInTheDocument(); }); it('updates content on change', async () => { // Test implementation }); });
Backend Tests
# backend/tests/test_agents.py import pytest from agents.writing_assistant import WritingAssistant @pytest.mark.asyncio async def test_writing_assistant(): agent = WritingAssistant() state = { "content": "This is a test", "messages": [{"role": "user", "content": "Improve this"}], } result = await agent.process(state) assert "messages" in result
Deployment
Frontend Deployment (Vercel)
cd frontend vercel deploy --prod
Backend Deployment (Railway/Render)
# Dockerfile for backend FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000"]
Best Practices Checklist
When building the application, ensure:
Architecture
- Clear separation between frontend and backend
- Type-safe communication (TypeScript + Pydantic)
- Shared state schema between frontend and backend
- Proper error handling and fallbacks
CopilotKit Integration
- Context providers configured for editor state
- Custom actions defined for common tasks
- Proper streaming for long responses
- Keyboard shortcuts configured
LangGraph Implementation
- Agents properly isolated with clear responsibilities
- State transitions well-defined
- Error recovery mechanisms
- Logging and observability (LangSmith)
Editor Experience
- Responsive UI with loading states
- Undo/redo functionality
- Auto-save and persistence
- Keyboard shortcuts
- Accessibility (ARIA labels)
Performance
- Debounced state updates
- Lazy loading for heavy components
- Optimized bundle size
- Caching for API responses
Security
- API key protection (server-side only)
- Input validation
- Rate limiting
- CORS properly configured
- Sanitized user inputs
Common Pitfalls to Avoid
- ❌ Exposing API keys in frontend code
- ❌ Not handling agent failures gracefully
- ❌ Blocking UI while waiting for agent responses
- ❌ Not validating state updates from agents
- ❌ Forgetting to cleanup WebSocket connections
- ❌ Not implementing proper error boundaries
- ❌ Ignoring TypeScript errors
- ❌ Not testing on different screen sizes
- ❌ Hardcoding backend URLs
- ❌ Not implementing proper loading states
Example Use Cases
1. AI-Powered Writing App
- Editor: Rich text (TipTap)
- Agents: Writing assistant, grammar checker, style improver
- Features: Real-time suggestions, tone adjustment, expansion
2. Code Collaboration Tool
- Editor: Monaco (VS Code)
- Agents: Code assistant, reviewer, documentation generator
- Features: Code completion, bug detection, auto-documentation
3. Workflow Designer
- Editor: ReactFlow nodes
- Agents: Workflow optimizer, validator, template suggester
- Features: Smart node suggestions, validation, auto-layout
Reference Documentation
For detailed implementation patterns and API references:
- CopilotKit integration patternsreferences/copilotkit-patterns.md
- LangGraph agent implementationsreferences/langgraph-agents.md
- State synchronization patternsreferences/state-management.md
- Editor-specific implementationsreferences/editor-integrations.md
Post-Setup Checklist
After scaffolding, guide the user to:
- ✅ Configure environment variables (.env)
- ✅ Set up OpenAI or LLM provider API key
- ✅ Test frontend development server
- ✅ Test backend API server
- ✅ Verify CopilotKit connection
- ✅ Test agent responses
- ✅ Customize agent prompts
- ✅ Add custom actions
- ✅ Implement additional features
- ✅ Deploy to production
Troubleshooting
CopilotKit not connecting
- Verify
is correctruntimeUrl - Check CORS configuration on backend
- Ensure backend is running
Agents not responding
- Check API keys are configured
- Verify LangGraph state schema matches
- Check backend logs for errors
Editor state not syncing
- Verify
is calleduseCopilotReadable - Check WebSocket connection
- Ensure state updates are properly dispatched
Version Compatibility
This skill targets:
- React: 18+
- CopilotKit: Latest (@copilotkit/react-core)
- LangGraph: Latest (langgraph)
- Python: 3.9+
- Node.js: 18+
- TypeScript: 5+
Next Steps
After scaffolding:
- Customize agent prompts for your use case
- Add domain-specific actions
- Implement additional editor features
- Set up analytics and monitoring
- Plan deployment strategy
- Create user documentation