Real-Time Collaborative Code Editor & Secure Execution Sandbox
Zero local setup required. Sub-millisecond CRDT document sync, full Monaco editor integration, and V8 sandboxed execution directly in your browser.
Problem & Solution β’ Features β’ Architecture β’ Tech Stack β’ Quick Start β’ Configuration β’ API Reference β’ Deployment
- π― Problem & Solution
- β¨ Features
- ποΈ Architecture
- π§° Tech Stack
- π Quick Start
- βοΈ Configuration
- π‘ API & WebSocket Reference
- π Security Guardrails
- π³ Deployment
- π Project Structure
- π€ Contributing
- π License
Remote pair-programming and technical interviews face three primary friction points:
- Sync Latency & Edit Collisions: Traditional lock-based editors cause operational collisions, lost keystrokes, and jitter when multiple engineers edit simultaneously.
- Environment Setup Overhead: Setting up matching runtimes, packages, and local compilers across developer machines consumes valuable time.
- Execution Security Risks: Running untrusted user code on shared servers opens severe remote code execution (RCE) and resource exhaustion risks.
SyncIDE delivers a zero-setup, production-ready collaborative sandbox directly in the browser:
- Conflict-Free CRDT Sync: Powered by Yjs, keystrokes, cursors, and selections sync peer-to-peer without central state lock contention.
- Full VS Code Editing: Monaco Editor integration brings syntax highlighting, auto-completion, minimap, multi-file workspace tabs, and keybindings.
- Isolated V8 Code Sandbox: User code is evaluated server-side within an isolated, memory-bounded (128 MB) and time-boxed (10s)
isolated-vmengine with real-time streaming output logs.
- β‘ Real-Time CRDT Collaboration: Sub-millisecond text synchronization via Yjs with remote presence indicators and live cursor tracking.
- π» Monaco Code Editor: Full-featured VS Code editing experience with syntax highlighting, language detection, and light/dark theme toggles.
- π‘οΈ Isolated Code Sandbox: Safely run JS and TS on the server inside
isolated-vmwith strict memory (128 MB) and timeout (10s) caps. - π TypeScript Support: Client-transparent TypeScript transpilation via
esbuildbefore sandbox evaluation. - π Multi-File Workspace Explorer: Create, rename, delete, and switch between project files with automatic syntax recognition.
- π¬ In-Session Collaborative Chat: Integrated chat panel with unread badge alerts, tab notification badges, and synced message history.
- π¬ Line-by-Line Code Annotations: Right-click lines to add contextual inline code comments with author color badges and resolution toggles.
- π¦ One-Click Workspace Export: Download your complete multi-file project workspace as a structured
.ziparchive viaJSZip. - πΎ WAL-Mode SQLite Persistence: Edits auto-persist to SQLite in Write-Ahead Logging mode with 1-second debounce buffers and 5-minute compaction cycles.
- π³ Alpine Docker Packaging: Multi-stage build producing a lightweight container (~150 MB total) ready for GCP, AWS, or Docker Compose.
flowchart TB
subgraph Clients ["Browser Clients"]
C1["Client A (React 19 + Monaco)"]
C2["Client B (React 19 + Monaco)"]
end
subgraph Transport ["Real-Time Protocol"]
WS["WebSocket / Socket.io Protocol"]
end
subgraph Server ["Node.js Backend Engine"]
YSO["YSocketIO Room Manager"]
AUTH["Session & Capacity Guard"]
VM["isolated-vm V8 Sandbox (128MB, 10s)"]
ESB["esbuild Compiler"]
PERSIST["SQLite Persistence Adapter (1s Debounce)"]
end
subgraph Storage ["Database Layer"]
DB[("SQLite Database (WAL Mode)\ndatabase.sqlite")]
end
C1 <-->|"Yjs CRDT Sync"| WS
C2 <-->|"Yjs CRDT Sync"| WS
WS <--> YSO
YSO --> AUTH
YSO --> PERSIST
PERSIST <--> DB
C1 -.->|"execute event"| WS
WS -.-> VM
VM <--> ESB
VM -.->|"stdout / stderr stream"| WS
- Handshake & Auth: Clients connect to room namespace
/yjs|{ROOM_CODE}. The server validates 5-character alphanumeric room codes, checks capacity (MAX_ROOM_SIZE), and prevents username duplication. - State Hydration: Server fetches historical updates from SQLite via
dbService.jsand syncs the liveY.Doc. - Incremental Debounced Storage: Edits queue in memory and flush to SQLite after 1 second of inactivity. Automated 5-minute compaction keeps database size minimal.
- Sandboxed Code Execution: When Run is clicked, code streams via WebSocket to
isolated-vm. Standard console logs (stdout/stderr) stream back to all room collaborators in real time.
| Layer | Technology | Purpose |
|---|---|---|
| Frontend Framework | React 19, Vite 7 | High-performance UI rendering and instant HMR |
| Code Editor | Monaco Editor (@monaco-editor/react) |
Web-based VS Code editing core |
| CRDT Collaboration | Yjs, y-monaco, y-socket.io |
Conflict-Free Replicated Data Types engine |
| Styling & UI | Tailwind CSS 4, Lucide Icons | Responsive layout design and icon system |
| Backend Runtime | Node.js 22, Express 5 | HTTP REST API and WebSocket gateway |
| Real-Time Network | Socket.io 4, y-socket.io |
Room namespace management & bi-directional streaming |
| Execution Sandbox | isolated-vm, esbuild |
Secure isolated V8 execution & fast TS compilation |
| Database & Storage | SQLite 3 (better-sqlite3) |
High-throughput WAL-mode persistent storage |
| Containerization | Docker (Alpine Multi-stage) | Production container deployment packaging (~150 MB) |
Get SyncIDE running locally in under 5 minutes.
- Node.js β₯
22.x - npm β₯
10.x - Build Tools: Python 3, Make, and C++ compiler (GCC/Clang on Linux/macOS, MSVC or Windows Build Tools on Windows) β required to build native C++ modules (
better-sqlite3andisolated-vm).
git clone https://github.com/Amruth0-0/SyncIDE.git
cd SyncIDEcd Backend
npm install
npm run devServer starts on http://localhost:3000.
In a new terminal window:
cd Frontend
npm install
npm run devApp launches on http://localhost:5173.
Open http://localhost:5173, choose a username, enter any 5-character room code (e.g. SYNC1), and start pair-programming!
| Parameter | Type | Default | Description |
|---|---|---|---|
PORT |
number |
3000 |
HTTP and WebSocket server port. |
MAX_ROOM_SIZE |
number |
2 |
Maximum concurrent users per room. |
ALLOWED_ORIGIN |
string |
* |
CORS origin policy (set to frontend domain in production). |
ADMIN_SECRET_KEY |
string |
(none) | Admin token required for protected room management endpoints. |
DATABASE_PATH |
string |
/app/data/database.sqlite |
Path to SQLite database file. |
| Parameter | Type | Default | Description |
|---|---|---|---|
VITE_API_URL |
string |
http://localhost:3000 |
Backend API server URL. Defaults to window origin in production. |
Service health check probe endpoint.
- Response:
{ "success": true, "message": "OK" }
Fetch active member count and capacity status.
- Rate Limit: 100 requests / minute per IP
- Response:
{ "roomCode": "SYNC1", "activeUsersCount": 1, "maxRoomSize": 2, "isFull": false, "success": true }
Permanently purge a room and wipe database records.
- Headers:
x-admin-token: <ADMIN_SECRET_KEY> - Response:
{ "success": true, "message": "Room SYNC1 deleted." }
execute: Send code for sandbox execution.{ "code": "console.log('Hello');", "language": "javascript" }execution-started: Broadcast to collaborators when code execution begins.execution-output: Real-time output stream chunk{ "type": "stdout" | "stderr", "text": "Hello\n" }.execution-finished: Broadcast when code execution finishes or times out.
- V8 Process Isolation: Code executes inside unprivileged
isolated-vmcontexts with zero access to Node.js core modules (fs,net,child_process). - Resource Constraints: Capped at 128 MB RAM per isolate with a strict 10-second timeout.
- Rate Control: Maximum 1 concurrent execution per room and 5 code executions per minute per room.
Build and run the unified Alpine production image (serves frontend static assets directly from backend Express server):
# 1. Build optimized Alpine image (~150 MB)
docker build -t syncide:latest .
# 2. Run container with persistent data volume
mkdir -p $(pwd)/data
docker run -d \
--name syncide \
-p 3000:3000 \
-v $(pwd)/data:/app/data \
-e DATABASE_PATH=/app/data/database.sqlite \
-e MAX_ROOM_SIZE=5 \
syncide:latestApplication will be available at http://localhost:3000.
- Run the Docker container on your Cloud VM (e.g. GCP
e2-micro) on port 3000. - Configure Nginx reverse proxy on port 80/443 with WebSocket upgrading:
server { listen 80; server_name syncide.duckdns.org; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; } }
- Issue free SSL via Certbot:
sudo certbot --nginx -d syncide.duckdns.org
SyncIDE/
βββ Backend/
β βββ config/ # Environment configuration & validation
β βββ controllers/ # Express route controllers
β βββ jobs/ # Scheduled cleanup cron tasks (>30d stale rooms)
β βββ middlewares/ # Auth, CORS, & rate limiting middlewares
β βββ routes/ # API route definitions
β βββ services/ # SQLite DB service, isolated-vm, & room logic
β βββ sockets/ # Socket.io authentication & Yjs persistence
β βββ utils/ # Room code validators
β βββ server.js # Main Express & Socket.io server entrypoint
β βββ package.json
βββ Frontend/
β βββ src/
β β βββ components/ # Monaco editor, Chat, Sidebar, Toolbar UI
β β βββ context/ # AppContext global React state & Yjs bindings
β β βββ utils/ # JSZip export & language mapping helpers
β βββ index.html
β βββ vite.config.js
β βββ package.json
βββ ARCHITECTURE.md # Scaling & PostgreSQL migration specification
βββ dockerfile # Production multi-stage Alpine Docker build
βββ README.md # Primary project documentation
Contributions are welcome! Please follow these steps:
- Fork the repository.
- Create a feature branch:
git checkout -b feature/my-cool-feature. - Commit your changes:
git commit -m 'feat: add my cool feature'. - Push to your branch:
git push origin feature/my-cool-feature. - Open a Pull Request.
Please ensure your code builds cleanly (npm run build in Frontend) before opening PRs.
This project is licensed under the GNU General Public License v3.0.