Real-time collaborative document editor — Google Docs-style editing powered by ProseMirror's operational transformation.
🔗 Live Demo · API Server
- Rich Text Editing — Full formatting with TipTap (bold, italic, headings, lists, links, images)
- Real-time Collaboration — Multiple users editing simultaneously with conflict resolution
- Live Word Count — Character and word statistics updated in real-time
- Persistence — Documents survive server restarts
- Operational Transformation — ProseMirror's battle-tested collab algorithm
| Layer | Technology |
|---|---|
| Frontend | React, TypeScript, TipTap, Vite |
| Backend | Node.js, Express, TypeScript |
| Collaboration | ProseMirror collab plugin (OT-based) |
| Deployment | Vercel (client), Railway (server) |
- Node.js 18+
- npm or yarn
# Clone the repo git clone https://github.com/Saumya29/co-write.git cd co-write # Start the server cd server npm install npm run dev # → http://localhost:4000 # Start the client (new terminal) cd client npm install npm run dev # → http://localhost:3000
Open multiple browser tabs to test collaboration!
co-write/
├── client/ # React + TipTap frontend
│ ├── src/
│ │ ├── components/ # Editor, Toolbar, MenuBar
│ │ ├── hooks/ # useCollaboration, useEditor
│ │ ├── api/ # Collaboration API client
│ │ └── lib/ # Utilities
│ └── README.md
│
├── server/ # Express backend
│ ├── src/
│ │ ├── modules/ # Feature modules
│ │ │ └── collaboration/
│ │ ├── routes.ts
│ │ └── index.ts
│ └── data/ # Persistence (state.json)
│
└── README.md
| Endpoint | Method | Description |
|---|---|---|
/health |
GET | Health check |
/api/version |
GET | Get current document version |
/api/events?version={n} |
GET | Get steps since version n |
/api/events |
POST | Submit new steps |
{
"version": 5,
"steps": [...],
"clientID": "abc123"
}Following ProseMirror's official collab example — HTTP polling is simpler, avoids reconnection complexity, and works well for collaborative editing. The 1-second polling interval provides near-real-time updates. WebSockets can be added later for lower latency.
ProseMirror's OT algorithm handles concurrent edits gracefully. When two users type simultaneously, their changes are transformed to maintain consistency across all clients.
Current: File-based persistence (server/data/state.json) — great for prototypes.
Production path:
- PostgreSQL for ACID transactions and ordered step storage
- Redis for caching recent steps
- Database constraints to enforce step ordering across multiple servers
- TipTap editor with rich text formatting
- Live word/character counter
- ProseMirror collab plugin integration
- Step synchronization between clients
- Document state catch-up on reload
- Debounced step sending (300ms)
- File-based persistence
- Automatic state recovery on startup
- User cursors/presence
- Multiple documents
- User authentication
- Import repo on vercel.com
- Set Root Directory to
client - Set Framework to
Vite - Add env:
VITE_API_URL=https://your-server.railway.app/api
- Create project on railway.app
- Connect GitHub repo
- Set Root Directory to
server - Build:
npm install && npm run build - Start:
npm start
Built by Saumya Tiwari