A proof-of-concept multi-document collaborative workspace with an AI writing assistant. Built to explore real-time collaborative editing where an AI agent operates as a first-class Yjs client alongside human users.
- Multi-document workspace — tabbed editor with drag-to-reorder, create, and delete
- Real-time collaboration — Yjs CRDT documents synced via y-websocket, supporting multiple concurrent editors
- Dual editor modes — Raw (CodeMirror 6 with markdown syntax highlighting) and Clean (MDXEditor WYSIWYG rich editor), with a single toggle that applies globally
- AI as a Yjs client — the AI assistant connects to the same y-websocket server as browsers, reading and writing documents through standard Yjs operations with a visible typewriter cursor
- AI chat sidebar — conversational interface where the AI can list, read, edit, append to, create, and request deletion of documents using tool calls
- Inline rework — select text in the editor, type an instruction, and the AI rewrites just that selection in-place
- Cross-document links — markdown links between documents (
[Title](/doc/uuid)) are clickable in both editor modes - AI activity indicators — pulsing dot on tabs when the AI is reading or writing a document
Browser (React/Next.js) Server
┌─────────────────────┐ ┌──────────────────┐
│ CollabEditor (CM6) │◄──►│ │
│ CleanView (MDXEditor│ │ y-websocket │
│ ChatSidebar │ │ (port 1234) │
│ DocTabs │ │ │
└─────────────────────┘ └──────────────────┘
▲
│ Yjs sync
▼
┌──────────────────┐
│ AI Yjs Singleton │
│ (Next.js server) │
│ /api/chat │
│ /api/rework │
└──────────────────┘
- y-websocket server — standalone WebSocket server for Yjs document sync with LevelDB persistence
- Next.js app — serves the UI and API routes
- AI Yjs Singleton — server-side Yjs client that connects to the same y-websocket server, enabling the AI to read/write documents with full CRDT awareness
- Next.js 14 (App Router)
- React 18
- Yjs + y-websocket + y-leveldb
- CodeMirror 6 + y-codemirror.next
- MDXEditor (Lexical-based WYSIWYG)
- AI SDK v6 + Anthropic Claude
- Tailwind CSS
- TypeScript
- Node.js 18+
- pnpm
- An Anthropic API key (for AI features)
# Install dependencies
pnpm install
# Create your environment file
cp .env.local.example .env.local
# Edit .env.local and add your ANTHROPIC_API_KEY
# Start both the Next.js dev server and y-websocket server
pnpm devThis runs two processes concurrently:
- Next.js dev server on
http://localhost:3000 - y-websocket server on
ws://localhost:1234
# With the dev servers running, test the server-side Yjs client
pnpm gate2This runs a Node.js script that connects to the y-websocket server as a second client, publishes an awareness cursor, and types text into the document — verifying the core "AI as Yjs client" architecture.
src/
├── app/
│ ├── api/
│ │ ├── chat/route.ts # Multi-turn AI chat endpoint (tool-calling)
│ │ ├── rework/route.ts # Inline selection rework endpoint
│ │ └── bootstrap-index/ # Index seeding endpoint
│ ├── layout.tsx
│ ├── page.tsx # Main workspace page
│ └── globals.css
├── components/
│ ├── collab-editor.tsx # Per-document editor (CM6 + Yjs binding)
│ ├── clean-view.tsx # WYSIWYG view (MDXEditor + Y.Text bridge)
│ ├── chat-sidebar.tsx # AI chat panel
│ ├── doc-tabs.tsx # Tab bar with drag-to-reorder
│ ├── editor-mode-toggle.tsx # Raw/Clean mode switcher
│ ├── selection-popover.tsx # Inline AI rework popover
│ ├── empty-state.tsx # Zero-docs welcome screen
│ └── delete-confirmation-modal.tsx
├── lib/
│ ├── ai-yjs-writer.ts # Server-side AI Yjs singleton
│ ├── use-doc-index.ts # Browser-side index hook
│ └── doc-nav-context.tsx # Navigation context
scripts/
│ └── gate2-test.cjs # Server-side Yjs client test
server/
│ └── websocket.cjs # y-websocket server with LevelDB
MIT