Back to projects
Live Project

CodeForge IDE

A lightweight, browser-based code editor built for quick prototyping. Supports multi-tab editing, real-time preview, syntax highlighting for 15+ languages, and collaborative sessions via WebSockets.

Role
Full-Stack Developer
Timeline
3 months
Stack
React, Monaco, Node.js
Status
Production
codeforge.jyra.dev CodeForge IDE
CodeForge IDE interface

Why build another editor?

Existing online editors are either too bloated for quick experiments or too limited for anything beyond a single file. I wanted something in between — fast enough to open in a second, powerful enough to handle a multi-file project with live reload.

The goal was simple: open a browser tab, write code, see it run. No account required, no build step, no friction.

How it works under the hood

🖥️
Browser
React + Monaco
🔌
WebSocket
Sync Layer
⚙️
Node.js
Server + VM2
💾
File Store
SQLite
CodeForge architecture diagram
fig.1 — Request lifecycle: browser ↔ sync server ↔ sandbox runner

The editor runs Monaco (the engine behind VS Code) in the browser. Code execution happens server-side inside a sandboxed VM2 instance. File state syncs through WebSockets for real-time collaboration.

Speed matters

<800 ms Boot Time
15+ Languages
50ms Sync Latency
Tabs

What makes it different

Instant Boot

Opens in under 800ms. No loading spinners, no SDK downloads.

📁

Multi-Tab Files

Create, rename, and switch between files like a desktop IDE.

👁️

Live Preview

HTML/CSS/JS renders instantly in a sandboxed iframe.

🤝

Collaboration

Share a link — others see your cursor and edits in real time.

🎨

Themes & Fonts

12 built-in themes, custom font support, adjustable font size.

🔒

Sandboxed Execution

Server-side code runs in isolated VM2 containers. No escape.

📦

npm Packages

Import npm modules directly. Bundled on-the-fly with esbuild.

💾

Auto Save

Every keystroke is saved. Close the tab, come back — it's there.

WebSocket sync layer

sync-server.js
import { WebSocketServer } from 'ws';
import { applyPatch, createDiff } from './diff-engine.js';

const wss = new WebSocketServer({ port: 8080 });
const rooms = new Map();

wss.on('connection', (ws, req) => {
  const roomId = req.url.slice(1);

  // Join or create room
  if (!rooms.has(roomId)) {
    rooms.set(roomId, { clients: new Set(), doc: '' });
  }
  const room = rooms.get(roomId);
  room.clients.add(ws);

  // Send current state to new client
  ws.send(JSON.stringify({
    type: 'init',
    doc: room.doc,
    users: room.clients.size
  }));

  ws.on('message', (data) => {
    const patch = JSON.parse(data);
    room.doc = applyPatch(room.doc, patch);

    // Broadcast to other clients
    room.clients.forEach(client => {
      if (client !== ws && client.readyState === 1)
        client.send(data);
    });
  });

  ws.on('close', () => {
    room.clients.delete(ws);
    if (room.clients.size === 0) rooms.delete(roomId);
  });
});
sandbox-runner.js
import { VM } from 'vm2';

const executeCode = (code, timeout = 5000) => {
  const output = [], errors = [];
  const vm = new VM({
    timeout,
    sandbox: {
      console: {
        log: (...a) => output.push(a.join(' ')),
        error: (...a) => errors.push(a.join(' ')),
      }
    },
    eval: false,
    wasm: false,
  });
  try {
    return { output, errors, result: vm.run(code) };
  } catch (e) {
    return { output, errors: [e.message], result: null };
  }
};

Technologies used

React 18Monaco EditorNode.js WebSocketsVM2SQLite esbuildDockerViteTypeScript

Interested in this project?

Check out the other experiments or get in touch.

View all projects