Skip to content

Parthmudgal15105/CollabCode

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

CollabCode

Real-time collaborative code editor with integrated WebRTC video calling for pair programming and technical interviews.


Features

Feature Details
Collaborative Editor Monaco Editor with live code sync, shared cursors, language switching
Video / Audio Peer-to-peer WebRTC (camera, mic, screen share)
Chat Real-time room chat with typing indicators
Code Execution Local Docker-based execution engine with sandboxed containers for Node.js, Python, Java, and C++
Room System Create / join rooms by ID, optional access-code for private rooms
Interview Mode Timer, problem statement panel, private interviewer notes
Auth Register / Login / Guest access (JWT)
Persistence Code auto-saved to MongoDB every 5 s, restored on reconnect
Reconnection Socket.io auto-reconnect, WebRTC ICE restart on failure

Tech Stack

Layer Technology
Frontend React 18, TypeScript, Vite
Styling Tailwind CSS
Editor Monaco Editor (@monaco-editor/react)
State Zustand
Real-time Socket.io
Video WebRTC (native browser API)
Backend Node.js, Express, TypeScript
Database MongoDB (Mongoose)
Code Exec Local Docker Containers

Project Structure

CollabCode/
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”‚   └── database.ts          # MongoDB connection
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   β”œβ”€β”€ ExecutionJob.ts      # Queued room execution jobs + polling state
β”‚   β”‚   β”‚   β”œβ”€β”€ User.ts              # User model (bcrypt hashed passwords)
β”‚   β”‚   β”‚   └── Room.ts              # Room model (code, messages, settings)
β”‚   β”‚   β”œβ”€β”€ controllers/
β”‚   β”‚   β”‚   └── code.ts              # /api/code/run controllers
β”‚   β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   β”‚   β”œβ”€β”€ auth.ts              # /api/auth (register, login, guest)
β”‚   β”‚   β”‚   β”œβ”€β”€ code.ts              # /api/code/run (queue + polling)
β”‚   β”‚   β”‚   β”œβ”€β”€ rooms.ts             # /api/rooms (CRUD)
β”‚   β”‚   β”‚   └── execute.ts           # /api/execute legacy compatibility route
β”‚   β”‚   β”œβ”€β”€ socket/
β”‚   β”‚   β”‚   └── index.ts             # All Socket.io event handlers
β”‚   β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”‚   β”œβ”€β”€ codeExecutor.ts      # Export wrapper for executeCode
β”‚   β”‚   β”‚   β”œβ”€β”€ dockerExecutor.ts    # Docker-based compilation and execution engine
β”‚   β”‚   β”‚   └── executionQueue.ts    # In-memory worker queue for room runs
β”‚   β”‚   β”œβ”€β”€ middleware/
β”‚   β”‚   β”‚   └── auth.ts              # JWT middleware
β”‚   β”‚   └── index.ts                 # Express + Socket.io server
β”‚   β”œβ”€β”€ .env.example
β”‚   β”œβ”€β”€ package.json
β”‚   └── tsconfig.json
β”‚
└── frontend/
    β”œβ”€β”€ src/
    β”‚   β”œβ”€β”€ components/
    β”‚   β”‚   β”œβ”€β”€ editor/
    β”‚   β”‚   β”‚   β”œβ”€β”€ CodeEditor.tsx       # Monaco + collaboration logic
    β”‚   β”‚   β”‚   └── LanguageSelector.tsx
    β”‚   β”‚   β”œβ”€β”€ video/
    β”‚   β”‚   β”‚   β”œβ”€β”€ VideoGrid.tsx        # Video tiles + media controls
    β”‚   β”‚   β”‚   └── VideoTile.tsx        # Individual participant tile
    β”‚   β”‚   β”œβ”€β”€ chat/
    β”‚   β”‚   β”‚   └── ChatPanel.tsx        # Chat + typing indicators
    β”‚   β”‚   β”œβ”€β”€ console/
    β”‚   β”‚   β”‚   └── ConsolePanel.tsx     # Stdin + execution output
    β”‚   β”‚   β”œβ”€β”€ room/
    β”‚   β”‚   β”‚   └── ParticipantList.tsx
    β”‚   β”‚   β”œβ”€β”€ interview/
    β”‚   β”‚   β”‚   β”œβ”€β”€ ProblemPanel.tsx     # Problem statement
    β”‚   β”‚   β”‚   └── InterviewControls.tsx # Timer + private notes (host)
    β”‚   β”‚   └── layout/
    β”‚   β”‚       └── MainLayout.tsx       # Workspace layout (3-panel)
    β”‚   β”œβ”€β”€ hooks/
    β”‚   β”‚   β”œβ”€β”€ useSocket.ts             # Socket.io event listeners + actions
    β”‚   β”‚   └── useWebRTC.ts             # WebRTC peer mesh management
    β”‚   β”œβ”€β”€ pages/
    β”‚   β”‚   β”œβ”€β”€ Auth.tsx                 # Login / Register / Guest
    β”‚   β”‚   β”œβ”€β”€ Home.tsx                 # Create / Join room
    β”‚   β”‚   └── Room.tsx                 # Room entry point
    β”‚   β”œβ”€β”€ services/
    β”‚   β”‚   β”œβ”€β”€ api.ts                   # Axios API client
    β”‚   β”‚   └── socket.ts                # Socket.io client singleton
    β”‚   β”œβ”€β”€ store/
    β”‚   β”‚   └── useStore.ts              # Zustand global store
    β”‚   └── types/
    β”‚       └── index.ts                 # Shared TypeScript types
    β”œβ”€β”€ .env.example
    β”œβ”€β”€ package.json
    β”œβ”€β”€ tailwind.config.js
    └── vite.config.ts

Setup & Running

Prerequisites

  • Node.js 18+
  • MongoDB (local or MongoDB Atlas)
  • Docker (must be installed and running for the local code execution engine)

1. Clone and install dependencies

# Backend
cd backend
npm install

# Frontend
cd ../frontend
npm install

2. Configure environment variables

# Backend
cp backend/.env.example backend/.env
# Edit backend/.env with your values:
#   MONGODB_URI, JWT_SECRET

# Frontend
cp frontend/.env.example frontend/.env

3. Start MongoDB (if running locally)

mongod --dbpath /data/db
# or with Docker:
docker run -d -p 27017:27017 mongo:7

4. Start the backend

cd backend
npm run dev
# Server runs on http://localhost:4000

5. Start the frontend

cd frontend
npm run dev
# App runs on http://localhost:5173

Open http://localhost:5173 in your browser.


Environment Variables

Backend (backend/.env)

Variable Required Default Description
PORT No 4000 Server port
MONGODB_URI Yes β€” MongoDB connection string
JWT_SECRET Yes β€” JWT signing secret
JWT_EXPIRES_IN No 7d Token expiry
FRONTEND_URL No http://localhost:5173 CORS origin
DOCKER_MEMORY_LIMIT No 256m Memory limit per execution container
DOCKER_CPU_LIMIT No 0.5 CPU limit per execution container
DOCKER_PIDS_LIMIT No 64 Process ID limit per execution container

Additional execution settings:

  • CODE_RUNNER_CONCURRENCY: number of room execution jobs processed in parallel
  • EXECUTION_JOB_TTL_HOURS: how long execution job documents stay in MongoDB

Frontend (frontend/.env)

Variable Required Default Description
VITE_BACKEND_URL No http://localhost:4000 Backend Socket.io URL

In development the Vite proxy forwards /api requests to the backend automatically.


Architecture Decisions

Collaborative Editing β€” Last-Write-Wins with Debounce

Monaco's onChange is debounced at 80 ms before emitting a code-change event.
The server broadcasts the new code to all other participants.
A isRemoteChange flag prevents re-broadcasting remote changes back to the server.

For teams > 4 or high-frequency typing, upgrade to Yjs + y-monaco (CRDT):

npm install yjs y-monaco y-websocket

WebRTC β€” Full Mesh

Each participant creates a direct RTCPeerConnection to every other participant.
This works well up to ~6 users (15 connections at max). For larger rooms, add a Selective Forwarding Unit (SFU) like mediasoup or LiveKit.

Signalling flow:

User A joins room
  └─ server sends 'existing-peers' list to A
      └─ A creates RTCPeerConnection for each existing peer
          └─ A sends webrtc-offer β†’ server β†’ peer
              └─ peer sends webrtc-answer β†’ server β†’ A
                  └─ ICE candidates exchanged β†’ media flows

Socket.io Room State

Active user presence is held in memory on the server using a Map<roomId, ActiveUser[]>.
Code is persisted to MongoDB every 5 seconds using a debounced scheduleSave().
On reconnect, joining the room re-sends the full room-state event with the latest code.

Code Execution

Primary room execution flow:

  1. POST /api/code/run queues an execution job with roomId, sourceCode, language, languageId, and stdin
  2. The backend worker spins up or reuses a Docker container configured for the submitted language.
  3. The source code is compiled (if necessary) and executed against the local Docker instance via spawn.
  4. GET /api/code/run/:executionId returns the execution status along with standard outputs and metrics.
  5. The frontend console displays stdout, stderr, compile output, status, time, and memory once the execution completes.

Primary execution routes:

  • POST /api/code/run
  • GET /api/code/run/:executionId

The room UI now uses the queued REST flow above. The older /api/execute route and socket execution events remain as legacy paths mapping to the new Docker executor.

Mode When Safety
Local Docker Room runs and direct compatibility executes Sandboxed lightweight local containers spawned with restrictive memory & CPU bounds

The current room execution system relies on the local Docker engine. Ensure Docker is running in the background before interacting with execution features.


Socket Event Reference

Client β†’ Server

Event Payload Description
join-room { roomId, accessCode? } Join a room
leave-room { roomId } Leave a room
code-change { roomId, code, version } Broadcast code update
cursor-change { roomId, position } Broadcast cursor position
language-change { roomId, language } Change editor language
send-message { roomId, text } Send chat message
typing { roomId } Typing indicator
execute-code { roomId, code, language, stdin } Legacy compatibility run event
toggle-interview-mode { roomId, enabled } Host: toggle interview mode
update-problem { roomId, problem } Host: update problem statement
update-notes { roomId, notes } Host: update private notes
update-timer { roomId, seconds } Host: sync timer
webrtc-offer { to, offer } WebRTC offer (relay)
webrtc-answer { to, answer } WebRTC answer (relay)
webrtc-ice-candidate { to, candidate } ICE candidate (relay)
media-state-change { roomId, videoOn, audioOn } Camera/mic toggle

Server β†’ Client

Event Payload Description
room-state { room, participants, isHost } Full state on join
user-joined { participant } New participant joined
user-left { socketId, userId } Participant left
existing-peers { peers } Existing peers for WebRTC init
code-updated { code, version, authorId } Remote code change
cursor-updated { userId, username, position } Remote cursor
language-changed { language } Language changed
message-received { userId, username, text, timestamp } New chat message
user-typing { userId, username } Typing indicator
execution-started β€” Legacy compatibility signal for direct socket execution
execution-result ExecutionResult Legacy compatibility result for direct socket execution
interview-mode-changed { enabled } Interview mode toggled
problem-updated { problem } Problem statement changed
timer-updated { seconds } Timer synced
webrtc-offer { from, offer, fromUser } Forwarded offer
webrtc-answer { from, answer } Forwarded answer
webrtc-ice-candidate { from, candidate } Forwarded ICE candidate
peer-media-changed { socketId, videoOn, audioOn } Peer media state

Future Extensions

  • Yjs CRDT β€” conflict-free collaborative editing at scale
  • SFU (mediasoup / LiveKit) β€” video for 10+ participants
  • Recording β€” save sessions to S3
  • Themes β€” light mode, custom editor themes
  • AI hints β€” GPT-powered code suggestions in the problem panel
  • Test runner β€” unit test support alongside code execution
  • Room history β€” time-travel through code snapshots
  • OAuth β€” GitHub / Google login

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors