ColabCode is a production-grade real-time collaborative coding platform built for technical interviews, DSA practice, and pair programming. Two or more developers share a live Monaco editor, structured file system, real PTY terminal, sandboxed code execution, and peer-to-peer video call — all in the browser, with zero setup.
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ Browser A WebSocket + Redis Browser B │
│ ───────── ──────────────── ───────── │
│ Monaco+Yjs ───────► Relay + CRDT sync ◄─────── Monaco+Yjs │
│ WebRTC ───────► SDP / ICE relay ◄─────── WebRTC │
│ Terminal ───────► PTY bash session ────────► xterm.js │
│ Run button ───────► Docker container ────────► Output panel │
│ (isolated) │
│ │
└─────────────────────────────────────────────────────────────────────┘
| Feature | Details | |
|---|---|---|
| ⚡ | Real-time collaborative editing | Monaco editor synced via Yjs CRDT — per-file document isolation, zero merge conflicts |
| 👁️ | Live cursors and presence | Every user's cursor, name, and color broadcast in real time via Socket.io awareness |
| 📁 | Shared file system | Recursive folder tree (adjacency list in Postgres) — create/rename/delete synced instantly to all room members |
| 🖥️ | Real PTY terminal | node-pty spawns genuine bash sessions per user, relayed over WebSocket to xterm.js |
| Sandboxed code execution | Docker containers — network disabled, 128MB RAM cap, 0.5 CPU, 10s hard kill — JS · Python · C++ · Bash | |
| 🎥 | Peer-to-peer video/audio | WebRTC with Socket.io signaling — SDP offer/answer and ICE candidate relay |
| 🔐 | Auth with OTP verification | JWT access + refresh token rotation, bcrypt hashing, email OTP via SMTP |
| 🏠 | Room management | Create rooms, share invite codes, manage members with owner vs member permissions |
| 💾 | Persistent document state | Yjs snapshots debounced to Postgres — late joiners and reconnects restore full document state |
| 📡 | Horizontally scalable WS | Socket.io Redis pub/sub adapter — multi-instance deployment without in-process state coupling |
| 🌐 | HTML/CSS/JS live preview | CSS and JS assets inlined from file tree into iframe — linked files just work |
┌───────────────────────────────────────────────────────────────────────┐
│ CLIENT (Vercel) │
│ React 18 · TypeScript · Tailwind · Vite · Zustand · React Router │
│ │
│ ┌──────────────┐ ┌─────────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Monaco + Yjs │ │FileExplorer │ │ xterm.js │ │ VideoPanel │ │
│ │ y-monaco │ │ Zustand │ │ PTY ws │ │ WebRTC P2P │ │
│ └──────┬───────┘ └──────┬──────┘ └────┬─────┘ └──────┬──────┘ │
└─────────┼─────────────────┼──────────────┼────────────────┼──────────┘
│ HTTPS + WSS │ │ │
┌─────────┼─────────────────┼──────────────┼────────────────┼──────────┐
│ NGINX (SSL · Port 80/443 → 3000 · WS upgrade) │
├─────────┼─────────────────┼──────────────┼────────────────┼──────────┤
│ SERVER (AWS EC2 · PM2) │
│ Express · Socket.io · node-pty · Prisma · Zod │
│ │
│ ┌──────────┐ ┌─────────┐ ┌──────────┐ ┌────────┐ ┌─────────┐ │
│ │ Yjs sync │ │ Files │ │ Terminal │ │ RTC │ │ Exec │ │
│ │ CRDT+DB │ │ CRUD │ │ PTY │ │ Signal │ │ Docker │ │
│ └──────────┘ └─────────┘ └──────────┘ └────────┘ └─────────┘ │
├───────────────────────────────────────────────────────────────────────┤
│ DATA LAYER │
│ PostgreSQL (users · rooms · files · sessions) │
│ Redis (Socket.io pub/sub · presence hashes · sessions) │
│ Docker (network:none · mem:128MB · cpu:0.5 · ttl:10s) │
└───────────────────────────────────────────────────────────────────────┘
The client connects over WSS to a Node.js/Socket.io server behind Nginx on EC2. Collaborative editing uses Yjs CRDT — each file has its own document that accumulates updates in memory and debounces saves to Postgres every 2 seconds, so late joiners always receive full document state. Redis serves three roles: Socket.io pub/sub adapter for horizontal scaling, session storage, and room presence via hash sets. Code execution spawns throwaway Docker containers with all network access disabled and memory/CPU hard-capped. WebRTC video uses Socket.io as the signaling channel, establishing direct peer-to-peer media streams after SDP/ICE exchange.
Node.js 20+ PostgreSQL Redis Docker Desktop
git clone https://github.com/riteshrana12-dev/ColabCode.git
cd ColabCodecd server
npm installCreate server/.env:
PORT=3000
DATABASE_URL=postgresql://postgres:password@localhost:5432/colabcode
REDIS_URL=redis://localhost:6379
JWT_SECRET=your_jwt_secret_minimum_32_chars
CLIENT_URL=http://localhost:5173
# Email OTP
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your@gmail.com
SMTP_PASS=your_gmail_app_passwordnpx prisma migrate dev
npm run devcd client
npm installCreate client/.env:
VITE_API_URL=http://localhost:3000/api/v1
VITE_WS_URL=http://localhost:3000
VITE_ENABLE_EXECUTION=truenpm run devOpen http://localhost:5173 🎉
ColabCode/
├── client/ # React + Vite frontend
│ └── src/
│ ├── components/
│ │ ├── editor/ # Monaco + Yjs + cursors + tabs
│ │ ├── explorer/ # File tree + context menu
│ │ ├── terminal/ # xterm.js + output panel
│ │ └── video/ # WebRTC video grid (Google Meet style)
│ ├── hooks/ # useCollabEditor · useWebRTC
│ ├── pages/ # Landing · Login · Dashboard · Room
│ ├── services/ # axios instance + Socket.io client
│ └── store/ # Zustand — editor · file · room · auth
│
└── server/ # Node.js + Express backend
└── src/
├── websocket/ # Socket.io modular handlers
│ ├── init.ts # Redis adapter + JWT middleware
│ ├── presence.ts # Room join/leave + Redis hashes
│ ├── yjs.ts # CRDT sync + debounced DB persistence
│ ├── files.ts # File tree broadcast
│ ├── terminal.ts # PTY lifecycle management
│ ├── rtc.ts # WebRTC SDP/ICE signaling
│ └── exec.ts # Docker sandbox execution
├── execution/ # Docker runner + image builder
├── terminal/ # node-pty session manager
├── services/ # workspace sync · access control
└── prisma/ # Schema + migrations
| Current | Production path |
|---|---|
| Docker execution on EC2 — not available on standard PaaS | Firecracker microVMs or gVisor for true multi-tenant isolation |
| WebRTC STUN only — may fail on restricted NAT networks | Self-host coturn TURN server or Metered.ca managed TURN |
| Terminal is per-user PTY — not shared between room members | tmux-style PTY broadcast for shared terminal sessions |
| File content stored as text in Postgres | S3/MinIO object storage for large binary files |
| No version control integration | git clone/push/pull inside workspace terminal |
| Single EC2 instance | Horizontal scaling already wired via Redis adapter — add load balancer |