A web-based Arduino simulator that provides an interactive code editor, compilation and Arduino Preview for Arduino sketches directly in the browser.
- Code Editor: Monaco editor integration for writing Arduino sketches with syntax highlighting
- Compilation: Compile Arduino code directly in the browser
- Serial Monitor: Real-time output display from simulated Arduino execution
- Pause/Resume Simulation: Pause running sketches to inspect state, change pin values, and resume execution
- Arduino Preview: A preview of analog/digital inputs and outputs directly in the Arduino SVG
- Web-based: No installation required, run entirely in the browser
- Modern UI: Built with React and TailwindCSS for a responsive, professional interface
- I/O Registry: You can see what Pins are used in your Program!
- Frontend: React, TypeScript, Vite, TailwindCSS, Radix UI
- Backend: Node.js (TypeScript), Express, WebSocket support
- Editor: Monaco Editor
- Testing: Vitest with React Testing Library
- Build Tools: Vite, esbuild
- Node.js (v18 or higher)
- npm or yarn
- Clone the repository:
git clone https://github.com/MoDevIO/UnoSim.git
cd UnoSim- Install dependencies:
npm install- Start the dev-server:
npm run dev:fullThis will start both the backend server and the frontend development server.
UnoSim can be run in several modes depending on your use case.
npm run dev:fullStarts the backend (Express + WebSocket) and the Vite dev server with hot-reload.
The backend runs via tsx (TypeScript execution) and the client is served by Vite on a separate port with HMR.
Compilation uses arduino-cli directly on the host — Docker is not required.
| Component | Details |
|---|---|
| Backend | tsx server/index.ts on port 3000 |
| Client | Vite HMR dev server (proxied) |
| Compiler | Direct arduino-cli calls on host |
| Worker Pool | Disabled (PooledCompiler.usePool = false outside production) |
npm run build
npm run startBuilds the full stack (client + server + worker) into dist/ and runs the production server.
The Vite-built client is served as static files from dist/public/.
| Component | Details |
|---|---|
| Backend | node dist/index.js on port 3000 |
| Client | Static files from dist/public/ |
| Compiler | Worker Pool with 4 parallel threads |
| Docker | Optional — enables sandboxed compilation if Docker Desktop is running |
Note: Docker warnings at startup (
Cannot connect to the Docker daemon) are non-blocking. The app falls back to directarduino-clicompilation when Docker is unavailable.
docker build -t unosim-sandbox:latest -f Dockerfile.sandbox .
docker build -t unosim:latest .
docker run --rm -p 3000:3000 -e NODE_ENV=production unosim:latestIf you start the image manually and want full Docker sandbox mode instead of the local fallback, use the same mounts and environment variables as Compose:
docker run --rm -p 3000:3000 \
-e NODE_ENV=production \
-e DOCKER_HOST=unix:///var/run/docker.sock \
-e DOCKER_SANDBOX_IMAGE=unosim-sandbox:latest \
-e ARDUINO_CACHE_DIR=/Users/to/Documents/TT_Web/UnoSim/server/arduino-cache \
-e UNOSIM_SHARED_TEMP_DIR=/Users/to/Documents/TT_Web/UnoSim/temp \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /Users/to/Documents/TT_Web/UnoSim/server/arduino-cache:/Users/to/Documents/TT_Web/UnoSim/server/arduino-cache \
-v /Users/to/Documents/TT_Web/UnoSim/temp:/Users/to/Documents/TT_Web/UnoSim/temp \
-v /Users/to/Documents/TT_Web/UnoSim/storage:/app/storage \
unosim-server:latestOr with Docker Compose (backend only):
docker compose up --buildThis will start the UnoSim backend only. Sandbox execution remains dynamic and uses the Docker socket at runtime.
If you need SonarQube, run it separately in its own stack or service; the UnoSim compose file does not include SonarQube or MCP.
The application runs inside a container and is available at http://localhost:3000.
For sandboxed sketch execution, the server container must use a temp directory that is bind-mounted from the host at the same absolute path. The provided Compose file does this via UNOSIM_SHARED_TEMP_DIR=/Users/to/Documents/TT_Web/UnoSim/temp and ./temp:/Users/to/Documents/TT_Web/UnoSim/temp.
On macOS, make sure /Users/to/Documents/TT_Web/UnoSim is allowed under Docker Desktop file sharing, otherwise the inner sandbox container cannot see generated files such as sketch.cpp.
| Command | Description |
|---|---|
npm run dev:full |
Start backend + client in development mode |
npm run dev |
Start backend only (no client) |
npm run dev:client |
Start Vite client only |
npm run build |
Build client, server, and worker for production |
npm run start |
Run the production build |
npm run check |
TypeScript type-check (tsc --noEmit) |
npm run test:fast |
Run unit tests (excludes load tests) |
npm test |
Run all tests |
./run-tests.sh |
Full pipeline: lint, unit tests, Docker build, integration tests, E2E |
- Sandbox Runner Pool — Manages a pool of sandbox processes that execute compiled Arduino binaries. Each simulation runs in an isolated child process with stdout/stderr capture for serial output and pin state reporting.
- Compilation Worker Pool — In production mode, 4 Node.js Worker Threads handle compilations in parallel via the
PooledCompiler. Each worker runsarduino-cliand caches build artifacts (hex files, core objects) for faster recompilation. - WebSocket Layer — Real-time communication between client and server for serial output, pin state batches, and simulation control (start/stop/pause/resume).
- SonarQube Integration — Quality gate checks are built into the pre-push hook and the test pipeline (
./run-tests.sh). Coverage reports are generated automatically.
The repository contains a robust, fast test pipeline:
- Unit tests (Vitest + React Testing Library) cover business logic and UI components. A full run exercises 869 tests with zero skips and completes in about 25 seconds on a modern laptop.
- Minimal E2E smoke flow comprises three Playwright tests that verify a
compile‑and‑run cycle, serial output and basic dialogs. This file lives in
e2e/smoke-and-flow.spec.tsand the entire suite now takes ~16 seconds instead of the previous 400+ second harness. Old specs have been archived/ignored. - Heavier integration/load tests under
tests/server/are marked skipped by default; setSKIP_LOAD_TESTS=1locally if you don’t have enough CPU or want a quick check.
Local quick‑check example:
SKIP_LOAD_TESTS=1 npm testIn CI, use a sufficiently‑powered runner and leave SKIP_LOAD_TESTS unset so the
performance tests run as intended.
🧹 After our recent refactor the pipeline runs in under a minute and should be very stable – feel free to run it before pushing changes.
MIT License - See LICENSE for details
This project uses third-party open-source dependencies. See THIRD_PARTY_LICENSES.txt for details.
- Issues & Bugs: Use the GitHub Issues tracker
- Feature Requests: Create an Pull Request
- Questions: Open a discussion or check existing issues
- Mo Tiltmann (MoDevIO) - Couven-Gymnasium, Aachen
- Tom Tiltmann (ttbombadil) - Technische Hochschule, Köln
The backend utilizes an Adapter Pattern for compilation:
-
PooledCompiler: Automatically manages task distribution.
-
Worker Isolation: Each compilation task runs in a separate thread, reducing API latency by ~30% under concurrent load.
-
Graceful Shutdown: Intelligent SIGTERM handling ensures all worker threads and file handles are closed properly.


