Building a Lightweight Web IDE

I needed a web IDE that runs on a Raspberry Pi 4. code-server (VS Code in the browser) uses 300-400MB RAM just sitting idle. My Pi has 4GB total. So I built one that uses ~30MB.

Bun server
->
React + Vite
->
Monaco Editor
->
xterm.js
->
tmux PTY

Why Not code-server?

code-server (VS Code)
RAM idle300-400MB
Bundle size~80MB
Startup3-5s
ExtensionsFull VS Code
web-ide-v3
RAM idle~30MB
Bundle size~250KB
Startup<1s
FeaturesFile editor + Terminal

code-server on a Raspberry Pi eating hundreds of MB of RAM just idling before opened a single file.
I don't need VS Code extensions, debugging, or git integration.
All I actually wanted was: edit files, run commands, keep the terminal alive when I close the tab. So instead of running a full IDE, I built just the three parts I need.

Stack

LayerTechWhy
RuntimeBunFaster than Node, native TypeScript, built-in bundler
ServerHonoLightweight, fast, similar to Express but smaller
FrontendReact + ViteFast builds, HMR for development
EditorMonacoSame engine as VS Code, great syntax highlighting
Terminalxterm.js + tmuxFull terminal emulation, session persistence
PTYBun.TerminalNative PTY support, no node-pty needed

How it Works

Server Architecture

Single Bun process handles everything: file API, static files, and WebSocket for terminal. No separate services, no nginx reverse proxy needed.
Server is Bun + Hono, one process, no build step for the backend. Frontend is React + Monaco for the editor, compiled with Vite and served as static files by the same Bun process.

"dependencies": {
  "@monaco-editor/react": "^4.7.0",
  "@xterm/xterm": "5.5.0",
  "@zuppif/termx": "^1.0.3",
  "hono": "^4.7.10",
  "react": "^19.0.0"
}

A Real Terminal

The terminal uses tmux for session persistence. When you close the browser and come back, your session is still alive. htop, editors, long-running commands. everything survives page reload.

tmux session runs in the background
WebSocket connects via tmux attach
On disconnect, tmux stays alive (session persists)
On reconnect, tmux attach sends current screen state
xterm.js handles all rendering and scrollback
Key tmux config: mouse off (xterm.js handles scroll), terminal-overrides xterm*:smcup@:rmcup@ (no alternate screen conflict).

File System API

Simple REST API for file operations. Supports multi-select, rename, delete, and right-click context menu. Files are served from the workspace directory.

# List files
GET /api/files?root=/home/user/project

# Read file
GET /api/file?path=src/index.ts

# Write file
POST /api/file
{"path": "src/index.ts", "content": "..."}

# Delete file
DELETE /api/file?path=old-file.txt

Run It

Requirements

Bun installed (curl -fsSL https://bun.sh/install | bash)
tmux (apt install tmux)

1. Clone and install

git clone https://github.com/MrFatoni/web-ide.git
cd web-ide
git checkout vite
bun install

2. Build and run

bun run build
bun run start

# Or with hot reload:
bun run dev

3. Open in browser

http://localhost:4242

# Or with custom workspace:
http://localhost:4242?root=/home/user/projects

4. Run as systemd service

sudo tee /etc/systemd/system/web-ide.service << 'EOF'
[Unit]
Description=Web IDE
After=network.target

[Service]
Type=simple
WorkingDirectory=/path/to/web-ide
Environment=PORT=4242
ExecStart=/home/user/.bun/bin/bun --hot run server/index.ts
Restart=always
RestartSec=3
User=your-username

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable --now web-ide

GitHub: github.com/MrFatoni/web-ide

Built with Bun, React, Vite, Monaco Editor, xterm.js, and tmux. Runs on ARM64 (Raspberry Pi) and x86_64.