A full-stack real-time collaborative code editor built with the MERN stack and Socket.io. Multiple users can join a shared room, write code together, chat, and execute code — all live.
- Create / Join rooms by ID
- Real-time collaborative editing (Monaco Editor)
- Multi-language support (JS, TS, Python, Java, C++, Go, Rust, Ruby)
- Live user presence list
- Real-time chat with typing indicators
- Code execution via Wandbox API (free, no API key required)
- JWT authentication (login / register)
- Save code sessions to MongoDB
- Version history (up to 20 snapshots)
- Restore previous versions
- Docker Compose support
Browser (React)
Monaco Editor --> socket.emit('code-change')
ChatPanel --> socket.emit('send-message')
|
| WebSocket (Socket.io)
v
Node.js / Express Server
roomHandler.js --> io.to(roomId).emit(...)
REST API --> /api/auth, /api/rooms, /api/execute
| |
v v
MongoDB Wandbox API
Users, Rooms Code execution
Chat, History
Event flow (code sync):
- User A types in editor →
onChangefires - Client emits
code-change→ server receives - Server broadcasts
code-updateto all others in the room - Their editors update via
isRemoteUpdateref guard (prevents echo loop)
- Node.js 18+
- MongoDB (local or Atlas)
- npm or yarn
cd server
cp .env.example .env
# Edit .env with your values
npm install
npm run devcd client
cp .env.example .env
npm install
npm run devMongoDB only:
docker-compose up mongodb -dFull containerized:
docker-compose up --build| Variable | Description | Default |
|---|---|---|
PORT |
Server port | 5001 |
CLIENT_URL |
Frontend URL (for CORS) | http://localhost:5173 |
MONGO_URI |
MongoDB connection string | mongodb://localhost:27017/codingplatform |
JWT_SECRET |
JWT signing secret | — |
JWT_EXPIRES_IN |
Token expiry | 7d |
No API key needed — code execution uses Wandbox, which is free with no signup.
| Variable | Description | Default |
|---|---|---|
VITE_SERVER_URL |
Backend URL | http://localhost:5001 |
| Event | Payload | Description |
|---|---|---|
join-room |
{ roomId, username } |
Join a collaborative room |
code-change |
{ roomId, code } |
Broadcast code update |
language-change |
{ roomId, language } |
Change editor language |
cursor-move |
{ roomId, cursor, username, color } |
Broadcast cursor position |
send-message |
{ roomId, username, message } |
Send chat message |
typing |
{ roomId, username, isTyping } |
Typing indicator |
save-code |
{ roomId, code, language, username } |
Save code snapshot |
| Event | Payload | Description |
|---|---|---|
room-state |
{ code, language, users } |
Initial state on join |
code-update |
{ code } |
Code changed by another user |
language-update |
{ language } |
Language changed |
user-joined |
{ username, socketId, color, users } |
Someone joined |
user-left |
{ username, socketId, users } |
Someone left |
chat-message |
{ type, username, message, timestamp } |
New chat message |
user-typing |
{ username, isTyping } |
Typing indicator |
cursor-update |
{ socketId, cursor, username, color } |
Cursor position |
code-saved |
{ username, timestamp, versions } |
Code snapshot saved |
| Method | Endpoint | Body | Auth | Description |
|---|---|---|---|---|
| POST | /api/auth/register |
{ username, email, password } |
No | Create account |
| POST | /api/auth/login |
{ email, password } |
No | Login, returns JWT |
| GET | /api/auth/me |
— | Bearer | Get current user |
| Method | Endpoint | Body | Auth | Description |
|---|---|---|---|---|
| POST | /api/rooms/create |
{ name?, language? } |
Bearer | Create room |
| GET | /api/rooms/:roomId |
— | No | Get room info |
| GET | /api/rooms/:roomId/chat |
— | No | Get chat history (last 100) |
| POST | /api/rooms/:roomId/save |
{ code, language, label? } |
Bearer | Save code snapshot |
| GET | /api/rooms/:roomId/versions |
— | Bearer | List version history |
| Method | Endpoint | Body | Auth | Description |
|---|---|---|---|---|
| POST | /api/execute |
{ code, language } |
No | Execute code via Wandbox |
coding-platform/
├── server/
│ ├── config/db.js
│ ├── middleware/auth.js
│ ├── models/
│ │ ├── User.js
│ │ ├── Room.js
│ │ └── ChatMessage.js
│ ├── routes/
│ │ ├── auth.js
│ │ ├── rooms.js
│ │ └── execute.js
│ ├── socket/roomHandler.js
│ ├── .env.example
│ ├── Dockerfile
│ └── index.js
│
├── client/
│ └── src/
│ ├── components/
│ │ ├── ChatPanel.jsx
│ │ ├── CodeEditor.jsx
│ │ ├── OutputPanel.jsx
│ │ ├── Toolbar.jsx
│ │ └── UserList.jsx
│ ├── context/AuthContext.jsx
│ ├── pages/
│ │ ├── EditorPage.jsx
│ │ ├── Home.jsx
│ │ ├── Login.jsx
│ │ └── Register.jsx
│ ├── utils/api.js
│ ├── App.jsx
│ ├── main.jsx
│ ├── socket.js
│ └── index.css
│
├── docker-compose.yml
├── .gitignore
└── README.md
Powered by Wandbox — a free, open-source compiler API with no API key or signup required.
Supported languages: JavaScript, TypeScript, Python, Java, C++, C, Go, Rust, Ruby.
If you get a 500 error from /api/execute, the compiler version names may have changed. Check the current list at https://wandbox.org/api/list.json and update server/routes/execute.js accordingly.
MIT