Replace Unix-only shell one-liner (mkdir -p / printf / cp -r) with a
Node.js ESM script (scripts/copy-monaco.mjs) that works on Windows,
macOS and Linux alike. The script still writes public/monaco/.gitignore
to keep copied assets out of git.
- postinstall now writes a '*' .gitignore into public/monaco/ so the
copied monaco-editor assets are never tracked as untracked files
- Also add public/monaco/ to frontend/.gitignore as a belt-and-suspenders
fallback for the same reason
This is Phase 1 of multi-language support: the visible chrome (header,
footer, language switcher) and routing are wired up for all 9 locales
(en, es, pt-br, it, fr, zh-cn, de, ja, ru) — same set the blog at
velxio.dev/blog/ already supports. The Editor and the long-form
landing-page copy are still English-only and will be translated in a
follow-up.
Infrastructure
- frontend/src/i18n/config.ts: locale registry + LOCALE_META (htmlLang,
native name, og locale, dir). Mirrors pro/blog/src/i18n/config.ts so
cookie sync stays consistent.
- frontend/src/i18n/cookie.ts: read/write the velxio_locale cookie at
Path=/; Max-Age=1y; SameSite=Lax (Secure on HTTPS). The blog reads
the same cookie via an inline script in its Layout.astro.
- frontend/src/i18n/path.ts: getLocaleFromPath / stripLocaleFromPath /
localizedPath / switchLocale / blogUrlFor — match the blog's helpers
one-to-one.
- frontend/src/i18n/index.ts: i18next bootstrap. English bundle is
inlined synchronously for first paint; non-default locales are
lazy-loaded via dynamic import on demand. Initial locale is decided
in priority order URL > cookie > navigator > en.
- frontend/src/i18n/LocaleSync.tsx: top-level wrapper inside <Router>.
On every URL change loads the matching locale bundle, calls
i18n.changeLanguage, writes the cookie, and mirrors the locale onto
<html lang> and dir.
- frontend/src/i18n/useLocalizedNavigate.ts: useCurrentLocale,
useLocalizedHref, useLocalizedNavigate hooks for components that
build internal links.
Routing
- App.tsx: route table extracted to a single ROUTES array, then
registered twice — once at the root (default English) and once
nested under each non-default locale (`/<locale>/...`). Explicit
per-locale parent routes (rather than a generic `:lang` param) so
React Router never accidentally swallows a real top-level path
like `/circuit-simulator` as a locale segment.
Header / Footer
- LanguageSwitcher.tsx + .css: dropdown matching the blog's
LanguageSwitcher.astro. Globe icon + locale code on the trigger,
native names + ISO codes in the menu. Click → `switchLocale()`
rewrites the URL under the new locale; LocaleSync handles the
rest (load bundle, change language, write cookie).
- AppHeader.tsx: every nav label and the auth dropdown copy now
goes through `t('header.nav.*')`, `t('header.auth.*')`. All
internal Links wrapped with localize() so navigation stays
inside the active locale. Added a "Blog" link computed via
`blogUrlFor(currentLocale)` so /es/ → /blog/es/, etc.
- LandingPage.tsx: footer About-Velxio paragraph reads from
t('footer.about').
Translations (Phase 1 strings)
- frontend/src/i18n/locales/<locale>/common.json: nav labels, auth
buttons, footer About copy. Hand-translated for all 9 locales,
AGPLv3 / brand names preserved as-is.
Tooling
- frontend/scripts/translate-i18n.mjs: standalone Node script that
takes the en.json bundles and auto-translates them to the 8 other
locales via DeepSeek (primary) + Gemini (fallback). One LLM call
per (locale, namespace) pair. Run after extracting new strings
with `npm run translate:i18n`.
Phase 2 (deferred)
- Editor (toolbar, file explorer, simulator canvas, component picker,
library manager, error toasts) — hundreds of strings.
- Examples / Docs / About / Profile pages.
- The translate-i18n.mjs script is ready to handle these once the
strings have been extracted into JSON keys.
Changes that ship to OSS — all benign for self-hosters, but most are
extension points the velxio-prod overlay (and any private fork) needs to
plug an in-editor AI chat into the page.
Editor:
- 3-way view-mode toggle (code / both / circuit) in the unified toolbar.
Lets users hide a pane to give a right-docked sidebar (e.g. the AI
chat overlay) more breathing room. Persisted in useEditorStore.
- Default file explorer narrower (210 → 165 px); min 110.
- Removed the redundant `tb-board-pill` (icon + "Editing: X" tooltip);
the BoardSelector dropdown elsewhere already shows the active board.
- Inlined Import/Export/Upload-firmware buttons; the 3-dot overflow
menu gave up too much discoverability. Removed dead overflow state.
Simulator:
- Fix: global Delete/Backspace handler in SimulatorCanvas no longer
fires when the event target is an INPUT/TEXTAREA/SELECT/contentEditable
— affected any in-page text field, not just the chat overlay.
Overlay extensibility:
- New `data-velxio-slot="agent-chat"` at the bottom of EditorPage so
pro overlays can portal a chat panel into the editor without
forking the page.
- vite.config.ts: preserveSymlinks=true when VITE_PRO_BUILD is set.
Lets local-dev junctions (overlay tree → frontend/src/pro) resolve
bare imports back to the OSS node_modules without resolving symlinks.
Deps:
- Added react-markdown + remark-gfm (rendered chat output) and
@google/genai + zod (overlay agent loop). Tree-shaken from the OSS
bundle when no pro code imports them.
gitignore:
- Ignore backend/app/pro/ and frontend/src/pro/ junctions used by
developers running a private overlay against the OSS dev server.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Foundation
- Add 7 token CSS files in src/tokens/ — semantic colors, 4-pt spacing,
Apple-HIG type ramp, radius/elevation/motion/z-index scales.
- Refactor src/index.css to import tokens and remap legacy aliases
(--accent, --bg, etc.) onto the new --color-* semantics so existing
components keep rendering during migration.
- Drop the duplicate font-family from src/App.css; body inherits from :root.
- Global *:focus-visible ring backed by --color-focus-ring (WCAG 2.4.7).
Webfonts (self-hosted)
- Add Inter.var.woff2 (variable, OFL) and JetBrainsMono.var.woff2 to
public/fonts/. Preloaded in index.html with crossorigin.
- Old stack -apple-system kept as fallback so Mac users still get SF Pro.
- Fixes cross-OS rendering inconsistency (Win/Linux/Android were falling
back to Segoe UI / Roboto, breaking the type grid).
Component primitives
- New src/components/ui/{Button,Card,Input}.tsx + .css. Built on the
semantic tokens, ready for incremental migration of .ap-* CSS classes.
Lucide icons
- Replace 6 inline SVG icon components in LandingPage (IcoChip / IcoCpu /
IcoCode / IcoZap / IcoLayers / IcoMonitor) with lucide-react imports.
Aliased so call sites are unchanged. ~80 lines of inline SVG removed.
- IcoGitHub kept bespoke (filled glyph, brand-correct).
Marketing assets
- Convert top 8 boards to transparent PNG + WebP at 1x / 2x:
Arduino Uno, Nano, Mega 2560, Pi Pico, Pi Pico W, ESP32-C3,
ESP32-DevKit-V1, XIAO ESP32-S3.
- Migrate matching cards in LandingPage and Velxio2Page to <picture>
with WebP > PNG > SVG fallback. Other 8 boards keep <img src=*.svg>
for now (Raspberry Pi 3B, ESP32-CAM, etc.).
- Refresh og-image.png — same canonical URL, new content (4 hero boards
+ branding instead of generic logo card).
- Fix latent bug in LandingPage: ESP32 DevKit V1 card was loading
esp32-devkit-c-v4.svg; now uses esp32-devkit-v1.{webp,png,svg}.
Build verified: npm run build:docker succeeds, 246 SEO pages prerender.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolves several install pain points reported by users (#108, #120) and
removes the obligatory upstream-clone step that confused contributors and
slowed down every Docker build.
Install fixes:
- nginx: server_name → catch-all default_server, drop Debian's stock site
so reverse-proxied users no longer get the "Welcome to nginx" page.
- entrypoint: auto-generate SECRET_KEY at first boot, persisted under
data/.secret_key. backend/.env is now optional in docker-compose.yml.
- backend: add greenlet>=3.0.0 (SQLAlchemy async dep that was missing on
some Python builds — caused uvicorn startup failures on WSL).
Wokwi libs come from npm:
- @wokwi/elements 1.9.2, avr8js 0.21.0, rp2040js 1.3.2 are pinned in
frontend/package.json. Vite aliases removed.
- Dockerfile.standalone no longer clones avr8js / rp2040js / wokwi-elements
/ wokwi-boards. Frontend stage is just COPY + npm install + build:docker.
- Board SVGs vendored under frontend/public/boards/ (10 deduped against
existing files, 2 truly new). third-party/wokwi-* clones become reference-
only credits — generate-component-metadata.ts skips gracefully when absent.
Production config split out:
- docker-compose.prod.yml, deploy/nginx.prod.conf, nginx-host-velxio*.conf,
update-third-party.bat removed. Production deployment lives in its own
repo: https://github.com/velxio/velxio-prod (host nginx + HTTPS + backups
+ pinned upstream commit).
Verified locally: 1161 frontend tests pass, build:docker completes clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The directory grew well beyond Wokwi-only contents: it now hosts
lcgamboa's QEMU fork (qemu-lcgamboa), Espressif's esp32-camera, the
ngspice WASM build, fritzing-parts, picowi, an alternative QEMU
(qemu-esp32), the 100_Days_100_IoT_Projects examples repo, and
Wokwi's own avr8js/rp2040js/wokwi-elements/wokwi-features/wokwi-boards.
"wokwi-libs" was misleading — half the contents have nothing to do
with Wokwi. "third-party/" is the standard convention for vendored
external dependencies.
Mechanical changes:
Path rename:
wokwi-libs/ → third-party/
update-wokwi-libs.bat → update-third-party.bat
docs/WOKWI_LIBS.md → docs/THIRD_PARTY.md
Submodule reconfiguration:
.gitmodules — 4 path= and section names updated
.git/modules/wokwi-libs/ → .git/modules/third-party/
each submodule's .git file rewired to ../../.git/modules/third-party/<name>
Reference updates (~80 files): vite.config.ts aliases, Dockerfile
COPY paths, GH Actions workflow steps, build_qemu_*.sh, all
docs/* and test/*/autosearch/* entries that mention the path,
package-lock.json file: dependencies, .gitignore patterns,
sitemap.xml + index.html SEO blurbs, scripts/generate-component-*,
.dockerignore, .idea/vcs.xml. Bulk replaced both `wokwi-libs/`
(path) and bare `wokwi-libs` (textual mentions in docs/comments).
Verified:
- npx tsc -b --noEmit produces no new errors related to these paths
- vite.config.ts aliases now point at ../third-party/avr8js etc.
- All 4 git submodules (avr8js, rp2040js, wokwi-elements,
wokwi-features) are linked under third-party/ with their
worktrees re-populated and config files referencing the new path
- `grep -r wokwi-libs` returns zero hits outside node_modules,
.vite, frontend/dist, third-party/ (upstream submodule contents),
*.pyc caches, and *.dll.pre-camera rollback binaries
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Track per-user, per-project, and per-board usage to inform pricing tier
decisions. Adds an admin dashboard with KPIs (DAU/WAU/MAU, totals,
success rate), time-series charts for compiles/runs, board family +
FQBN breakdowns, "board diversity" pie chart (key freemium signal),
top users/projects, and per-country breakdown via Cloudflare's
CF-IPCountry header. Admin can now also view private projects.
Backend:
- New UsageEvent table (append-only event log with user_id, project_id,
event_type, board_fqbn/family, country, error_kind, duration_ms)
- Aggregate counters on User (total_compiles/runs/errors, last_active,
signup_country, last_country) and Project (compile/run/update counts,
last_compiled/run timestamps) kept in sync by MetricsService for O(1)
dashboard reads
- 10 admin endpoints under /api/admin/metrics/{overview, timeseries,
boards, board-diversity, top-users, top-projects, countries,
users/{id}, projects/{id}}
- POST /api/metrics/run for client-side run telemetry
- Country detection via cf-ipcountry header (no DB / no API calls)
- Auto-migrations in lifespan for legacy DBs
Frontend:
- recharts-powered Dashboard tab with KPI cards and 4 charts
- New Boards tab with per-family + per-FQBN breakdown
- Country column with flag emoji on Users tab
- Top countries card on Dashboard
- compileCode now forwards project_id; Run button reports via WS
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Modified the index file to reflect the new naming convention for Velxio components.
- Changed JSX declarations to use 'velxio-' prefix for various components.
- Updated component overrides to replace 'wokwi-' with 'velxio-' for logic gates and other components.
- Adjusted SVG generation script to use 'velxio-' prefix for BMP280 and Raspberry Pi components.
- Marked submodules as dirty in QEMU and RP2040 libraries.
- Added .prettierignore and .prettierrc.json for consistent code formatting.
- Introduced InstrumentComponent with support for Voltmeter and Ammeter, including pin information handling.
- Implemented Bmp280Element as a custom web component for the BMP280 barometric sensor, including SVG representation and pin configuration.
- Created CircuitPreview component to render circuit thumbnails using SVGs of components, including support for various boards and components.
- Added a script to generate SVG files from wokwi-elements, ensuring proper formatting and structure for reliable rendering.
- Introduced a test HTML generation script to visualize component SVGs.
Implements MicroPython emulation for Raspberry Pi Pico boards running
entirely in the browser using rp2040js. Users can toggle between
Arduino C++ and MicroPython modes via a language selector dropdown.
Key changes:
- Add LanguageMode type and BOARD_SUPPORTS_MICROPYTHON to board types
- Create MicroPythonLoader.ts: UF2 firmware parser, LittleFS filesystem
builder (via littlefs-wasm), IndexedDB firmware caching
- Extend RP2040Simulator with loadMicroPython() method using USBCDC for
serial REPL instead of UART
- Add setBoardLanguageMode and loadMicroPythonProgram store actions
- Update EditorToolbar with language toggle and MicroPython compile flow
- Enhance SerialMonitor with REPL label, Ctrl+C/D support
- Bundle MicroPython v1.20.0 UF2 firmware as fallback in public/firmware/
- Update useEditorStore to create main.py default for MicroPython mode
Closes#3
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add VirtualFileSystem component for managing files and directories.
- Integrate useVfsStore for state management of the virtual file system.
- Implement context menu for file operations: New File, New Folder, Rename, Delete.
- Add upload functionality to send files to Raspberry Pi.
- Create default file structure for new Raspberry Pi boards.
- Enhance editor with board-aware features and compile/run orchestration.
- Introduce CompileAllProgress component for tracking compilation status across boards.
- Redesign SerialMonitor to support multiple boards with tabbed interface.
- Establish Raspberry Pi specific workspace with terminal and file system integration.
- Implemented `require_admin` dependency to enforce admin access control.
- Added `is_admin` column to the users table for role management.
- Created admin routes and schemas for user and project management.
- Developed AdminPage with user and project management tabs.
- Integrated user editing and deletion functionalities in the admin panel.
- Added setup screen for creating the first admin user.
- Updated frontend to include admin functionalities and user role display.
- Generated Open Graph image for better social media integration.
- Add live demo badge and link to velxio.dev at the top
- Add Docker single-container run command with volume mount
- Add env vars reference table
- Simplify and modernize overall structure
- Update package.json name and homepage to velxio.dev
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Added comprehensive SEO meta tags to `frontend/index.html` including Open Graph and Twitter Card data.
- Updated `frontend/public` with new favicon assets and a PWA manifest.
- Created a favicon generation script to automate favicon creation from SVG.
- Implemented `robots.txt` to allow all crawlers and point to the sitemap.
- Added `sitemap.xml` with public routes and priorities for better indexing.
- Created a new TypeScript file for component metadata types defining structure for dynamically loaded components.
- Implemented a metadata generator script that scans the wokwi-elements repository to extract component information, including properties and categories.
- Added package.json and package-lock.json for dependency management, including TypeScript and related tools.
- Introduced a new file to log ping statistics for testing purposes.
- Added SimulatorCanvas component for rendering the simulator interface.
- Integrated Wokwi components (Arduino, LED, Resistor, Pushbutton, Potentiometer) into the simulator.
- Created PinManager to handle pin state changes and notifications.
- Developed AVRSimulator class for emulating Arduino Uno functionality.
- Implemented hex file loading and compilation service.
- Added CSS styles for the simulator interface.
- Established Zustand stores for managing editor and simulator states.
- Created utility functions for parsing Intel HEX format.
- Set up Vite configuration for the frontend project.
- Added batch scripts for starting backend and frontend servers, and updating Wokwi libraries.