From c1b9244341b9f6344d18d16579c8efdcebf62610 Mon Sep 17 00:00:00 2001 From: Sipho Mokoena Date: Fri, 27 Mar 2026 01:59:48 +0000 Subject: [PATCH 1/8] feat: add VS Code devcontainer configuration with optimized setup - Add .devcontainer/devcontainer.json with Python 3.12 + Node 20 base image - Added remoteUser: vscode to avoid running as root - Configured named volumes for node_modules (frontend + 3 wokwi-libs) to improve I/O performance on non-Linux hosts - Added volume for arduino-cli cache at /home/vscode/.arduino15 - Added remoteEnv PATH to include node_modules/.bin and venv/bin - Configured port forwarding for 5173 (Vite) and 8001 (FastAPI) - Add .devcontainer/post-create.sh for initial container setup - Fix ownership of node_modules volumes with chown vscode:vscode - Install arduino-cli with sudo to /usr/local/bin - Install Arduino cores (arduino:avr, rp2040:rp2040) with duplicate guards - Set up Python venv with base deps (wheel, setuptools) before requirements.txt - Install npm deps with HUSKY=0 to disable git hooks in container environment - Build wokwi-libs (avr8js, rp2040js, wokwi-elements) in parallel - All installs run in parallel background jobs with wait for optimal performance - Add .devcontainer/post-start.sh for incremental updates on container restart - Lightweight sync of Python and npm dependencies - Runs on every container start for drift detection - Add wokwi-boards submodule for ESP32/Pico board SVG assets - Code imports board.svg files from wokwi-libs/wokwi-boards/boards/ - Submodule was referenced but not initialized, causing Vite import errors - Configure Vite to bind to 0.0.0.0:5173 for devcontainer port forwarding - Default 127.0.0.1 binding is not accessible from outside container - Explicit host/port config enables VS Code port forwarding to work --- .devcontainer/devcontainer.json | 46 +++++++++++++++++++++++ .devcontainer/post-create.sh | 65 +++++++++++++++++++++++++++++++++ .devcontainer/post-start.sh | 16 ++++++++ .gitmodules | 3 ++ frontend/vite.config.ts | 2 + 5 files changed, 132 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100755 .devcontainer/post-create.sh create mode 100644 .devcontainer/post-start.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..5838758 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,46 @@ +{ + "name": "Velxio", + "image": "mcr.microsoft.com/devcontainers/python:3.12", + "features": { + "ghcr.io/devcontainers/features/node:1": { + "version": "20", + "installGlobally": true + } + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python", + "ms-vscode.vscode-typescript-next", + "dbaeumer.vscode-eslint", + "bradlc.vscode-tailwindcss" + ] + } + }, + "remoteUser": "vscode", + "waitFor": "postCreateCommand", + "mounts": [ + "source=${localWorkspaceFolder}/wokwi-libs,target=/workspaces/velxio/wokwi-libs,type=bind,consistency=cached", + "source=velxio-arduino-cache,target=/home/vscode/.arduino15,type=volume", + "source=velxio-frontend-nodemodules,target=/workspaces/velxio/frontend/node_modules,type=volume", + "source=velxio-avr8js-nodemodules,target=/workspaces/velxio/wokwi-libs/avr8js/node_modules,type=volume", + "source=velxio-rp2040js-nodemodules,target=/workspaces/velxio/wokwi-libs/rp2040js/node_modules,type=volume", + "source=velxio-wokwi-elements-nodemodules,target=/workspaces/velxio/wokwi-libs/wokwi-elements/node_modules,type=volume" + ], + "postCreateCommand": "bash .devcontainer/post-create.sh", + "postStartCommand": "bash .devcontainer/post-start.sh", + "remoteEnv": { + "PATH": "${containerEnv:PATH}:/workspaces/velxio/frontend/node_modules/.bin:/workspaces/velxio/backend/venv/bin" + }, + "forwardPorts": [5173, 8001], + "portsAttributes": { + "5173": { + "label": "Frontend (Vite)", + "onAutoForward": "notify" + }, + "8001": { + "label": "Backend (FastAPI)", + "onAutoForward": "notify" + } + } +} diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh new file mode 100755 index 0000000..6dc38e6 --- /dev/null +++ b/.devcontainer/post-create.sh @@ -0,0 +1,65 @@ +#!/bin/bash +set -e + +cd /workspaces/velxio + +echo "==> Fixing ownership for mounted volumes..." +# Fix ownership of directories that are mounted as volumes +sudo chown -R vscode:vscode /workspaces/velxio/frontend/node_modules 2>/dev/null || true +sudo chown -R vscode:vscode /workspaces/velxio/wokwi-libs/avr8js/node_modules 2>/dev/null || true +sudo chown -R vscode:vscode /workspaces/velxio/wokwi-libs/rp2040js/node_modules 2>/dev/null || true +sudo chown -R vscode:vscode /workspaces/velxio/wokwi-libs/wokwi-elements/node_modules 2>/dev/null || true +sudo chown -R vscode:vscode /home/vscode/.arduino15 2>/dev/null || true + +echo "==> Installing arduino-cli..." +if ! command -v arduino-cli &> /dev/null; then + curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sudo BINDIR=/usr/local/bin sh +fi + +echo "==> Installing Arduino cores (this may take a few minutes)..." +sudo arduino-cli core update-index +if ! sudo arduino-cli core list | grep -q "arduino:avr"; then + sudo arduino-cli core install arduino:avr +fi + +# Add RP2040 board manager (guard against duplicates) +if ! sudo arduino-cli config get board_manager.additional_urls | grep -q "rp2040"; then + sudo arduino-cli config add board_manager.additional_urls https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json +fi +if ! sudo arduino-cli core list | grep -q "rp2040:rp2040"; then + sudo arduino-cli core install rp2040:rp2040 +fi + +echo "==> Setting up Python virtual environment (base layer)..." +(cd /workspaces/velxio/backend +python3 -m venv venv +./venv/bin/pip install wheel setuptools +./venv/bin/pip install -r requirements.txt) & + +echo "==> Installing frontend dependencies..." +(cd /workspaces/velxio/frontend +HUSKY=0 npm install) & + +echo "==> Building wokwi-libs..." +# Local wokwi-libs are cloned from GitHub instead of using npm packages. +# This allows us to modify the emulators and components for Velxio-specific behavior. +# Build outputs go to dist/ directories and are resolved via Vite aliases. +(cd /workspaces/velxio/wokwi-libs/avr8js +HUSKY=0 npm install +npm run build) & + +(cd /workspaces/velxio/wokwi-libs/rp2040js +HUSKY=0 npm install +npm run build) & + +(cd /workspaces/velxio/wokwi-libs/wokwi-elements +HUSKY=0 npm install +npm run build) & + +wait # Wait for all background jobs to complete + +echo "==> Dev environment ready!" +echo "" +echo "To start development:" +echo " Backend: cd backend && source venv/bin/activate && uvicorn app.main:app --reload --port 8001" +echo " Frontend: cd frontend && npm run dev" diff --git a/.devcontainer/post-start.sh b/.devcontainer/post-start.sh new file mode 100644 index 0000000..84895ed --- /dev/null +++ b/.devcontainer/post-start.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +cd /workspaces/velxio + +echo "==> Fixing ownership for mounted volumes..." +sudo chown -R vscode:vscode /workspaces/velxio/frontend/node_modules 2>/dev/null || true + +echo "==> Syncing Python dependencies..." +(cd /workspaces/velxio/backend +source venv/bin/activate +pip install -q -r requirements.txt) + +echo "==> Syncing frontend dependencies..." +cd /workspaces/velxio/frontend +HUSKY=0 npm install diff --git a/.gitmodules b/.gitmodules index 17c9e41..175529e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "wokwi-libs/wokwi-features"] path = wokwi-libs/wokwi-features url = https://github.com/wokwi/wokwi-features.git +[submodule "wokwi-libs/wokwi-boards"] + path = wokwi-libs/wokwi-boards + url = https://github.com/wokwi/wokwi-boards.git diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index fafeaad..3ec9b95 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -13,6 +13,8 @@ export default defineConfig({ }, }, server: { + host: '0.0.0.0', + port: 5173, proxy: { '/api': { target: 'http://localhost:8001', From c0720f0743ae18736f99e03c4029664ca2580c8e Mon Sep 17 00:00:00 2001 From: Sipho Mokoena Date: Fri, 27 Mar 2026 04:43:29 +0200 Subject: [PATCH 2/8] refactor: make devcontainer configuration portable and user-agnostic Improve devcontainer robustness by eliminating hardcoded paths and user assumptions: devcontainer.json changes: - Replace hardcoded /workspaces/velxio paths with ${containerWorkspaceFolder} variable - Ensures compatibility with GitHub Codespaces and other workspace path variations - Update all volume mount targets and PATH environment variable to use dynamic paths post-create.sh improvements: - Dynamically detect workspace root from script location instead of assuming /workspaces/velxio - Use $(whoami) to get current user instead of hardcoding 'vscode' user - Replace absolute paths with relative paths for all operations - Makes script work correctly in any devcontainer environment (VS Code, Codespaces, Gitpod) post-start.sh improvements: - Apply same dynamic workspace root detection pattern - Use current user instead of hardcoded 'vscode' for chown operations - Ensures ownership fixes work regardless of container user configuration These changes enable the devcontainer to work seamlessly across different hosting environments without requiring manual configuration adjustments. --- .devcontainer/devcontainer.json | 12 ++++++------ .devcontainer/post-create.sh | 27 ++++++++++++++++----------- .devcontainer/post-start.sh | 13 +++++++++---- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5838758..292cf8b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -20,17 +20,17 @@ "remoteUser": "vscode", "waitFor": "postCreateCommand", "mounts": [ - "source=${localWorkspaceFolder}/wokwi-libs,target=/workspaces/velxio/wokwi-libs,type=bind,consistency=cached", + "source=${localWorkspaceFolder}/wokwi-libs,target=${containerWorkspaceFolder}/wokwi-libs,type=bind,consistency=cached", "source=velxio-arduino-cache,target=/home/vscode/.arduino15,type=volume", - "source=velxio-frontend-nodemodules,target=/workspaces/velxio/frontend/node_modules,type=volume", - "source=velxio-avr8js-nodemodules,target=/workspaces/velxio/wokwi-libs/avr8js/node_modules,type=volume", - "source=velxio-rp2040js-nodemodules,target=/workspaces/velxio/wokwi-libs/rp2040js/node_modules,type=volume", - "source=velxio-wokwi-elements-nodemodules,target=/workspaces/velxio/wokwi-libs/wokwi-elements/node_modules,type=volume" + "source=velxio-frontend-nodemodules,target=${containerWorkspaceFolder}/frontend/node_modules,type=volume", + "source=velxio-avr8js-nodemodules,target=${containerWorkspaceFolder}/wokwi-libs/avr8js/node_modules,type=volume", + "source=velxio-rp2040js-nodemodules,target=${containerWorkspaceFolder}/wokwi-libs/rp2040js/node_modules,type=volume", + "source=velxio-wokwi-elements-nodemodules,target=${containerWorkspaceFolder}/wokwi-libs/wokwi-elements/node_modules,type=volume" ], "postCreateCommand": "bash .devcontainer/post-create.sh", "postStartCommand": "bash .devcontainer/post-start.sh", "remoteEnv": { - "PATH": "${containerEnv:PATH}:/workspaces/velxio/frontend/node_modules/.bin:/workspaces/velxio/backend/venv/bin" + "PATH": "${containerEnv:PATH}:${containerWorkspaceFolder}/frontend/node_modules/.bin:${containerWorkspaceFolder}/backend/venv/bin" }, "forwardPorts": [5173, 8001], "portsAttributes": { diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 6dc38e6..567e194 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -1,15 +1,20 @@ #!/bin/bash set -e -cd /workspaces/velxio +# Get the workspace root (devcontainer sets this as pwd, but we can also derive it from script location) +WORKSPACE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$WORKSPACE_ROOT" + +# Get current user dynamically +CURRENT_USER=$(whoami) echo "==> Fixing ownership for mounted volumes..." # Fix ownership of directories that are mounted as volumes -sudo chown -R vscode:vscode /workspaces/velxio/frontend/node_modules 2>/dev/null || true -sudo chown -R vscode:vscode /workspaces/velxio/wokwi-libs/avr8js/node_modules 2>/dev/null || true -sudo chown -R vscode:vscode /workspaces/velxio/wokwi-libs/rp2040js/node_modules 2>/dev/null || true -sudo chown -R vscode:vscode /workspaces/velxio/wokwi-libs/wokwi-elements/node_modules 2>/dev/null || true -sudo chown -R vscode:vscode /home/vscode/.arduino15 2>/dev/null || true +sudo chown -R "$CURRENT_USER:$CURRENT_USER" frontend/node_modules 2>/dev/null || true +sudo chown -R "$CURRENT_USER:$CURRENT_USER" wokwi-libs/avr8js/node_modules 2>/dev/null || true +sudo chown -R "$CURRENT_USER:$CURRENT_USER" wokwi-libs/rp2040js/node_modules 2>/dev/null || true +sudo chown -R "$CURRENT_USER:$CURRENT_USER" wokwi-libs/wokwi-elements/node_modules 2>/dev/null || true +sudo chown -R "$CURRENT_USER:$CURRENT_USER" "$HOME/.arduino15" 2>/dev/null || true echo "==> Installing arduino-cli..." if ! command -v arduino-cli &> /dev/null; then @@ -31,28 +36,28 @@ if ! sudo arduino-cli core list | grep -q "rp2040:rp2040"; then fi echo "==> Setting up Python virtual environment (base layer)..." -(cd /workspaces/velxio/backend +(cd backend python3 -m venv venv ./venv/bin/pip install wheel setuptools ./venv/bin/pip install -r requirements.txt) & echo "==> Installing frontend dependencies..." -(cd /workspaces/velxio/frontend +(cd frontend HUSKY=0 npm install) & echo "==> Building wokwi-libs..." # Local wokwi-libs are cloned from GitHub instead of using npm packages. # This allows us to modify the emulators and components for Velxio-specific behavior. # Build outputs go to dist/ directories and are resolved via Vite aliases. -(cd /workspaces/velxio/wokwi-libs/avr8js +(cd wokwi-libs/avr8js HUSKY=0 npm install npm run build) & -(cd /workspaces/velxio/wokwi-libs/rp2040js +(cd wokwi-libs/rp2040js HUSKY=0 npm install npm run build) & -(cd /workspaces/velxio/wokwi-libs/wokwi-elements +(cd wokwi-libs/wokwi-elements HUSKY=0 npm install npm run build) & diff --git a/.devcontainer/post-start.sh b/.devcontainer/post-start.sh index 84895ed..93267c0 100644 --- a/.devcontainer/post-start.sh +++ b/.devcontainer/post-start.sh @@ -1,16 +1,21 @@ #!/bin/bash set -e -cd /workspaces/velxio +# Get the workspace root +WORKSPACE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$WORKSPACE_ROOT" + +# Get current user dynamically +CURRENT_USER=$(whoami) echo "==> Fixing ownership for mounted volumes..." -sudo chown -R vscode:vscode /workspaces/velxio/frontend/node_modules 2>/dev/null || true +sudo chown -R "$CURRENT_USER:$CURRENT_USER" frontend/node_modules 2>/dev/null || true echo "==> Syncing Python dependencies..." -(cd /workspaces/velxio/backend +(cd backend source venv/bin/activate pip install -q -r requirements.txt) echo "==> Syncing frontend dependencies..." -cd /workspaces/velxio/frontend +cd frontend HUSKY=0 npm install From e0f97d460bbcbe23dd95d048cfdd89bfee33eaa7 Mon Sep 17 00:00:00 2001 From: Sipho Mokoena Date: Fri, 27 Mar 2026 04:18:50 +0000 Subject: [PATCH 3/8] feat: update devcontainer setup and add new submodule for qemu --- .devcontainer/devcontainer.json | 6 +----- .devcontainer/post-create.sh | 14 ++++++++------ .gitmodules | 6 ++++++ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 292cf8b..5ca5597 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -20,12 +20,8 @@ "remoteUser": "vscode", "waitFor": "postCreateCommand", "mounts": [ - "source=${localWorkspaceFolder}/wokwi-libs,target=${containerWorkspaceFolder}/wokwi-libs,type=bind,consistency=cached", "source=velxio-arduino-cache,target=/home/vscode/.arduino15,type=volume", - "source=velxio-frontend-nodemodules,target=${containerWorkspaceFolder}/frontend/node_modules,type=volume", - "source=velxio-avr8js-nodemodules,target=${containerWorkspaceFolder}/wokwi-libs/avr8js/node_modules,type=volume", - "source=velxio-rp2040js-nodemodules,target=${containerWorkspaceFolder}/wokwi-libs/rp2040js/node_modules,type=volume", - "source=velxio-wokwi-elements-nodemodules,target=${containerWorkspaceFolder}/wokwi-libs/wokwi-elements/node_modules,type=volume" + "source=velxio-frontend-nodemodules,target=${containerWorkspaceFolder}/frontend/node_modules,type=volume" ], "postCreateCommand": "bash .devcontainer/post-create.sh", "postStartCommand": "bash .devcontainer/post-start.sh", diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 567e194..35fbefa 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -9,12 +9,14 @@ cd "$WORKSPACE_ROOT" CURRENT_USER=$(whoami) echo "==> Fixing ownership for mounted volumes..." -# Fix ownership of directories that are mounted as volumes -sudo chown -R "$CURRENT_USER:$CURRENT_USER" frontend/node_modules 2>/dev/null || true -sudo chown -R "$CURRENT_USER:$CURRENT_USER" wokwi-libs/avr8js/node_modules 2>/dev/null || true -sudo chown -R "$CURRENT_USER:$CURRENT_USER" wokwi-libs/rp2040js/node_modules 2>/dev/null || true -sudo chown -R "$CURRENT_USER:$CURRENT_USER" wokwi-libs/wokwi-elements/node_modules 2>/dev/null || true -sudo chown -R "$CURRENT_USER:$CURRENT_USER" "$HOME/.arduino15" 2>/dev/null || true +for d in frontend/node_modules wokwi-libs/avr8js/node_modules wokwi-libs/rp2040js/node_modules wokwi-libs/wokwi-elements/node_modules "$HOME/.arduino15"; do + sudo chown -R "$CURRENT_USER:$CURRENT_USER" "$d" 2>/dev/null || true +done + +echo "==> Initializing git submodules..." +# Nuke everything except node_modules (which are Docker volumes - can't delete) +rm -rf wokwi-libs/avr8js/* wokwi-libs/rp2040js/* wokwi-libs/wokwi-elements/* wokwi-libs/wokwi-features/* wokwi-libs/wokwi-boards/* wokwi-libs/qemu-lcgamboa/* +git submodule update --init --recursive echo "==> Installing arduino-cli..." if ! command -v arduino-cli &> /dev/null; then diff --git a/.gitmodules b/.gitmodules index 175529e..f3e7c44 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,6 +13,12 @@ [submodule "wokwi-libs/wokwi-features"] path = wokwi-libs/wokwi-features url = https://github.com/wokwi/wokwi-features.git + [submodule "wokwi-libs/wokwi-boards"] path = wokwi-libs/wokwi-boards url = https://github.com/wokwi/wokwi-boards.git + +[submodule "wokwi-libs/qemu-lcgamboa"] + path = wokwi-libs/qemu-lcgamboa + url = https://github.com/lcgamboa/qemu.git + branch = picsimlab-esp32 From ae2a42f28d35c2971f92043395efad9f954faaf7 Mon Sep 17 00:00:00 2001 From: Sipho Mokoena Date: Fri, 27 Mar 2026 04:21:34 +0000 Subject: [PATCH 4/8] chore: remove qemu-esp32 submodule from wokwi-libs --- wokwi-libs/qemu-esp32 | 1 - 1 file changed, 1 deletion(-) delete mode 160000 wokwi-libs/qemu-esp32 diff --git a/wokwi-libs/qemu-esp32 b/wokwi-libs/qemu-esp32 deleted file mode 160000 index 33cc9a8..0000000 --- a/wokwi-libs/qemu-esp32 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 33cc9a8740071031e30704141d2803b308ce0d32 From abd7b6739843e3655f14b8fb468b13bddc3dc0c7 Mon Sep 17 00:00:00 2001 From: Sipho Mokoena Date: Fri, 27 Mar 2026 15:54:37 +0200 Subject: [PATCH 5/8] feat: add Makefile for simplified development commands and update README with usage instructions --- .devcontainer/README.md | 74 +++++++++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 2 +- .devcontainer/post-create.sh | 59 +++++++++++++++++++------- Makefile | 19 +++++++++ README.md | 6 +++ 5 files changed, 144 insertions(+), 16 deletions(-) create mode 100644 .devcontainer/README.md create mode 100644 Makefile diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 0000000..304ad3e --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,74 @@ +# DevContainer for Velxio + +This devcontainer provides a ready-to-use development environment for Velxio with: + +- Python 3.12 + FastAPI backend setup +- Node.js 20 + React/Vite frontend setup +- arduino-cli with AVR and RP2040 cores +- Built wokwi-libs (avr8js, rp2040js, wokwi-elements) +- Persistent volumes for node_modules and arduino cache + +## What's Included + +### Automatically Installed +- **Arduino AVR** — Arduino Uno, Nano, Mega emulation +- **RP2040** — Raspberry Pi Pico / Pico W emulation +- **Frontend tooling** — TypeScript, ESLint, Tailwind CSS +- **Backend tooling** — Python virtual environment with all dependencies + +### Not Included (Manual Setup) +- **ESP32 Emulation (QEMU)** — Requires platform-specific compilation + +## Why ESP32 QEMU is Manual + +ESP32 emulation requires building QEMU from the lcgamboa fork, which: +- Takes 15-30 minutes to compile +- Requires platform-specific tools (MSYS2 on Windows, build-essential on Linux) +- Generates 40-60 MB libraries excluded from git +- Is optional — AVR and RP2040 work without it + +**For Docker users:** ESP32 emulation is pre-built and included in the official image. + +**For development:** If you need ESP32 emulation, see [docs/ESP32_EMULATION.md](../docs/ESP32_EMULATION.md) + +## Getting Started + +1. Open this repository in VS Code with the Dev Containers extension +2. VS Code will automatically build and start the devcontainer +3. Wait for `post-create.sh` to complete (~5-6 minutes) +4. Start the backend: `cd backend && source venv/bin/activate && uvicorn app.main:app --reload --port 8001` +5. Start the frontend: `cd frontend && npm run dev` +6. Open http://localhost:5173 + +## Optimization Notes + +- **Shallow clones** — wokwi-libs use `--depth=1` for faster setup (not recursive submodules) +- **Parallel builds** — Backend, frontend, and wokwi-libs build concurrently +- **Volume mounts** — node_modules and arduino cache persist between rebuilds +- **User-local tools** — arduino-cli installs to `~/.local/bin` (no sudo required) + +## Ports Forwarded + +- **5173** — Frontend (Vite dev server) +- **8001** — Backend (FastAPI) + +## Troubleshooting + +### Builds are slow +First-time setup takes 5-6 minutes. Subsequent container starts use `post-start.sh` which only syncs dependencies (~30 seconds). + +### Permission errors on volumes +The `post-create.sh` script fixes ownership automatically. If you still see errors, rebuild the container. + +### Arduino cores missing +Check that arduino-cli is in PATH: +```bash +arduino-cli version +arduino-cli core list # should show arduino:avr and rp2040:rp2040 +``` + +## Related Documentation + +- [Getting Started](../docs/getting-started.md) — Manual setup instructions +- [ESP32 Emulation](../docs/ESP32_EMULATION.md) — Full ESP32 setup guide +- [Architecture](../docs/ARCHITECTURE.md) — Project architecture overview diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5ca5597..2dc692b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -26,7 +26,7 @@ "postCreateCommand": "bash .devcontainer/post-create.sh", "postStartCommand": "bash .devcontainer/post-start.sh", "remoteEnv": { - "PATH": "${containerEnv:PATH}:${containerWorkspaceFolder}/frontend/node_modules/.bin:${containerWorkspaceFolder}/backend/venv/bin" + "PATH": "${containerEnv:PATH}:/home/vscode/.local/bin:${containerWorkspaceFolder}/frontend/node_modules/.bin:${containerWorkspaceFolder}/backend/venv/bin" }, "forwardPorts": [5173, 8001], "portsAttributes": { diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 35fbefa..cf44fe9 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -13,60 +13,89 @@ for d in frontend/node_modules wokwi-libs/avr8js/node_modules wokwi-libs/rp2040j sudo chown -R "$CURRENT_USER:$CURRENT_USER" "$d" 2>/dev/null || true done -echo "==> Initializing git submodules..." -# Nuke everything except node_modules (which are Docker volumes - can't delete) -rm -rf wokwi-libs/avr8js/* wokwi-libs/rp2040js/* wokwi-libs/wokwi-elements/* wokwi-libs/wokwi-features/* wokwi-libs/wokwi-boards/* wokwi-libs/qemu-lcgamboa/* -git submodule update --init --recursive +echo "==> Cloning wokwi-libs (shallow, faster than submodules)..." +# Only clone the 3 libs we actually use (avr8js, rp2040js, wokwi-elements) +# Shallow clone with --depth=1 is much faster than recursive submodule init +for lib in avr8js rp2040js wokwi-elements; do + if [ ! -d "wokwi-libs/$lib/.git" ]; then + rm -rf "wokwi-libs/$lib" + git clone --depth=1 "https://github.com/wokwi/$lib.git" "wokwi-libs/$lib" + else + echo " -> wokwi-libs/$lib already exists, skipping clone" + fi +done -echo "==> Installing arduino-cli..." +echo "==> Installing arduino-cli (user-local)..." if ! command -v arduino-cli &> /dev/null; then - curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sudo BINDIR=/usr/local/bin sh + mkdir -p "$HOME/.local/bin" + curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR="$HOME/.local/bin" sh + export PATH="$HOME/.local/bin:$PATH" fi echo "==> Installing Arduino cores (this may take a few minutes)..." -sudo arduino-cli core update-index -if ! sudo arduino-cli core list | grep -q "arduino:avr"; then - sudo arduino-cli core install arduino:avr +arduino-cli core update-index +if ! arduino-cli core list | grep -q "arduino:avr"; then + arduino-cli core install arduino:avr fi # Add RP2040 board manager (guard against duplicates) -if ! sudo arduino-cli config get board_manager.additional_urls | grep -q "rp2040"; then - sudo arduino-cli config add board_manager.additional_urls https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json +if ! arduino-cli config get board_manager.additional_urls | grep -q "rp2040"; then + arduino-cli config add board_manager.additional_urls https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json fi -if ! sudo arduino-cli core list | grep -q "rp2040:rp2040"; then - sudo arduino-cli core install rp2040:rp2040 +if ! arduino-cli core list | grep -q "rp2040:rp2040"; then + arduino-cli core install rp2040:rp2040 fi +# Note: ESP32 emulation (QEMU lcgamboa) is NOT installed by this script. +# It requires platform-specific builds (MSYS2 on Windows, 15-30 min compile time) +# and generates 40-60 MB libraries that are excluded from git. +# - Docker images include pre-built QEMU libs automatically +# - Development without ESP32 emulation works fine (AVR/RP2040 only) +# - For full ESP32 support, see: docs/ESP32_EMULATION.md +# - Backend auto-detects and falls back to UART-only mode if libs are missing + echo "==> Setting up Python virtual environment (base layer)..." (cd backend python3 -m venv venv ./venv/bin/pip install wheel setuptools ./venv/bin/pip install -r requirements.txt) & +BACKEND_PID=$! echo "==> Installing frontend dependencies..." (cd frontend HUSKY=0 npm install) & +FRONTEND_PID=$! -echo "==> Building wokwi-libs..." +echo "==> Building wokwi-libs in parallel (avr8js, rp2040js, wokwi-elements)..." # Local wokwi-libs are cloned from GitHub instead of using npm packages. # This allows us to modify the emulators and components for Velxio-specific behavior. # Build outputs go to dist/ directories and are resolved via Vite aliases. (cd wokwi-libs/avr8js HUSKY=0 npm install npm run build) & +AVR_PID=$! (cd wokwi-libs/rp2040js HUSKY=0 npm install npm run build) & +RP2040_PID=$! (cd wokwi-libs/wokwi-elements HUSKY=0 npm install npm run build) & +ELEMENTS_PID=$! -wait # Wait for all background jobs to complete +echo " -> Waiting for all parallel builds to complete..." +wait $BACKEND_PID && echo " ✓ Backend deps installed" +wait $FRONTEND_PID && echo " ✓ Frontend deps installed" +wait $AVR_PID && echo " ✓ avr8js built" +wait $RP2040_PID && echo " ✓ rp2040js built" +wait $ELEMENTS_PID && echo " ✓ wokwi-elements built" echo "==> Dev environment ready!" echo "" echo "To start development:" echo " Backend: cd backend && source venv/bin/activate && uvicorn app.main:app --reload --port 8001" echo " Frontend: cd frontend && npm run dev" +echo "" +echo "Note: AVR/RP2040 emulation is ready. For ESP32 emulation (QEMU), see docs/ESP32_EMULATION.md" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cc57287 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +.PHONY: help dev-backend dev-frontend install clean + +.DEFAULT_GOAL := help + +help: ## Show available commands + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " %-15s %s\n", $$1, $$2}' + +dev-backend: ## Start backend (port 8001) + @cd backend && . venv/bin/activate && uvicorn app.main:app --reload --host 0.0.0.0 --port 8001 + +dev-frontend: ## Start frontend (port 5173) + @cd frontend && npm run dev + +install: ## Install dependencies + @cd backend && python3 -m venv venv && . venv/bin/activate && pip install -r requirements.txt + @cd frontend && npm install + +clean: ## Remove venv and node_modules + @rm -rf backend/venv frontend/node_modules diff --git a/README.md b/README.md index 6a93554..bff913c 100644 --- a/README.md +++ b/README.md @@ -292,6 +292,12 @@ docker compose -f docker-compose.prod.yml up -d git clone https://github.com/davidmonterocrespo24/velxio.git cd velxio +# With Makefile (Linux/macOS) +make install +make dev-backend +make dev-frontend + +# Or manually: # Backend cd backend python -m venv venv && source venv/bin/activate # Windows: venv\Scripts\activate From 9e5b08ee49c4ac127c45681bc553ba09f7eebf49 Mon Sep 17 00:00:00 2001 From: Sipho Mokoena Date: Fri, 27 Mar 2026 16:06:44 +0200 Subject: [PATCH 6/8] feat: enhance Makefile with improved dev command and installation messages --- Makefile | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index cc57287..7b567bb 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,17 @@ -.PHONY: help dev-backend dev-frontend install clean +.PHONY: help dev dev-backend dev-frontend install clean .DEFAULT_GOAL := help help: ## Show available commands @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " %-15s %s\n", $$1, $$2}' +dev: ## Start backend and frontend (requires tmux) + @if command -v tmux >/dev/null 2>&1; then \ + tmux new-session -d -s velxio 'make dev-backend' \; split-window -h 'make dev-frontend' \; attach; \ + else \ + echo "Install tmux or run 'make dev-backend' and 'make dev-frontend' in separate terminals"; \ + fi + dev-backend: ## Start backend (port 8001) @cd backend && . venv/bin/activate && uvicorn app.main:app --reload --host 0.0.0.0 --port 8001 @@ -12,8 +19,13 @@ dev-frontend: ## Start frontend (port 5173) @cd frontend && npm run dev install: ## Install dependencies + @echo "Installing root dependencies (tsx, typescript for build scripts)..." + @npm install + @echo "Installing backend dependencies..." @cd backend && python3 -m venv venv && . venv/bin/activate && pip install -r requirements.txt + @echo "Installing frontend dependencies..." @cd frontend && npm install + @echo "✓ All dependencies installed" clean: ## Remove venv and node_modules - @rm -rf backend/venv frontend/node_modules + @rm -rf backend/venv frontend/node_modules node_modules From 4f328c7e2f9329fa04e26dfe887bb970cfecab1a Mon Sep 17 00:00:00 2001 From: Sipho Mokoena Date: Fri, 27 Mar 2026 16:07:49 +0200 Subject: [PATCH 7/8] feat: enhance installation process by adding cloning and building of wokwi-libs --- .devcontainer/post-create.sh | 5 +++++ Makefile | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index cf44fe9..5f89baa 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -54,6 +54,10 @@ fi # - For full ESP32 support, see: docs/ESP32_EMULATION.md # - Backend auto-detects and falls back to UART-only mode if libs are missing +echo "==> Installing root dependencies (tsx, typescript for build scripts)..." +HUSKY=0 npm install & +ROOT_PID=$! + echo "==> Setting up Python virtual environment (base layer)..." (cd backend python3 -m venv venv @@ -86,6 +90,7 @@ npm run build) & ELEMENTS_PID=$! echo " -> Waiting for all parallel builds to complete..." +wait $ROOT_PID && echo " ✓ Root deps installed" wait $BACKEND_PID && echo " ✓ Backend deps installed" wait $FRONTEND_PID && echo " ✓ Frontend deps installed" wait $AVR_PID && echo " ✓ avr8js built" diff --git a/Makefile b/Makefile index 7b567bb..ed1a3b3 100644 --- a/Makefile +++ b/Makefile @@ -21,10 +21,22 @@ dev-frontend: ## Start frontend (port 5173) install: ## Install dependencies @echo "Installing root dependencies (tsx, typescript for build scripts)..." @npm install + @echo "Cloning wokwi-libs (shallow)..." + @for lib in avr8js rp2040js wokwi-elements; do \ + if [ ! -d "wokwi-libs/$$lib/.git" ]; then \ + rm -rf "wokwi-libs/$$lib"; \ + git clone --depth=1 "https://github.com/wokwi/$$lib.git" "wokwi-libs/$$lib"; \ + fi; \ + done @echo "Installing backend dependencies..." @cd backend && python3 -m venv venv && . venv/bin/activate && pip install -r requirements.txt @echo "Installing frontend dependencies..." @cd frontend && npm install + @echo "Building wokwi-libs..." + @for lib in avr8js rp2040js wokwi-elements; do \ + echo "Building $$lib..."; \ + cd "wokwi-libs/$$lib" && npm install && npm run build && cd ../..; \ + done @echo "✓ All dependencies installed" clean: ## Remove venv and node_modules From 87b1a75df0e21053c24868ce4a4e98305de4ae0d Mon Sep 17 00:00:00 2001 From: Sipho Mokoena Date: Fri, 27 Mar 2026 19:11:29 +0200 Subject: [PATCH 8/8] feat: add wokwi-boards to devcontainer post-create script --- .devcontainer/post-create.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 5f89baa..dcf1867 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -16,7 +16,7 @@ done echo "==> Cloning wokwi-libs (shallow, faster than submodules)..." # Only clone the 3 libs we actually use (avr8js, rp2040js, wokwi-elements) # Shallow clone with --depth=1 is much faster than recursive submodule init -for lib in avr8js rp2040js wokwi-elements; do +for lib in avr8js rp2040js wokwi-elements wokwi-boards; do if [ ! -d "wokwi-libs/$lib/.git" ]; then rm -rf "wokwi-libs/$lib" git clone --depth=1 "https://github.com/wokwi/$lib.git" "wokwi-libs/$lib"