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.
Three small, backwards-compatible hooks let anyone with private features
(velxio.dev's analytics, custom integrations, paid tiers, …) layer them
on top of the open-source build without forking files.
Backend (app/main.py):
- After standard router registration, try-import an optional `app.pro`
module exposing `register_pro(app)`. ImportError is silently swallowed
(the OSS image doesn't ship `app.pro`, so this is a no-op there).
Frontend:
- EditorToolbar: new optional `rightSlot` prop renders extra elements
after the built-in right-group buttons (mirrors the existing
`centerSlot` pattern).
- main.tsx: dynamic `import('@pro/index')` gated by VITE_PRO_BUILD env.
When unset (OSS build), the branch is dead-code-eliminated and no pro
chunk is emitted.
- vite.config.ts: `@pro` alias resolves to `src/__pro_stub__/` by default.
Private builds set `VITE_PRO_BUILD=true` and `PRO_OVERLAY_PATH=<path>`
to point at their real overlay tree.
- src/__pro_stub__/index.ts: 1-line no-op `mountPro` so TypeScript and
Vite resolvers stay happy in OSS builds.
Verified: `npm run build:docker` succeeds; `npm test` passes 1161/1162;
the OSS bundle (43 MB) contains zero references to `__pro_stub__`,
`@pro`, or `pro/index` (verified via `grep dist/`).
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>
- 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.
Adds 44 SPICE mappers, 58 custom metadata entries, and 12 visual
Web Components covering logic gates, transistors, op-amps, regulators,
sources, electromechanical parts and integrated-circuit packaging.
Fase 9 — component catalog expansion
------------------------------------
- 7 logic gates (AND/OR/NAND/NOR/XOR/XNOR + NOT) as SPICE B-sources
- 8 multi-input gates (AND/OR/NAND/NOR with 3 and 4 inputs)
- 9 transistors: 5 BJTs (incl. PNP 2N3906/BC557) + 4 MOSFETs (incl.
P-channel IRF9540/FQP27P06). NMOS refactored from Level=3 W=0.1
(hangs ngspice) to Level=1 with sane W/L
- 5 op-amps: LM358, LM741, TL072, LM324 with per-chip saturation
rails + opamp-ideal
- 4 linear regulators (7805, 7812, 7905, LM317) with dropout
- 3 batteries (9V, AA, coin-cell) with realistic ESR
- Signal generator (sine / square / DC)
- 2 Schottky diodes (1N5817, 1N5819) + photodiode (lux-driven
current source)
Fase 10 — electromechanical + ICs
---------------------------------
- Relay (SPDT): coil + L + S-switch with native hysteresis +
flyback diode, inverted-control trick for the NC contact
- Optocouplers 4N25 and PC817 (LED + CCCS with CTR=0.5 / 1.0)
- 7 74HC ICs as DIP-14 packages emitting 4 or 6 B-sources per
component (first mapper pattern emitting multiple device cards)
- 3 flip-flops (D, T, JK) — digital-sim only (edge detection is
not representable in ngspice .op)
- L293D dual H-bridge motor driver
Infrastructure
--------------
- scripts/component-overrides.json gains a _customComponents[] array
that lets new Velxio-only parts survive metadata regeneration
(previously applyOverrides() could only patch wokwi-elements
components that had already been scanned)
- scripts/generate-component-metadata.ts injects custom entries
before the patch loop
- New ComponentCategory values: 'logic', 'analog', 'electromech'
- frontend/src/components/DynamicComponent.tsx PASSIVE tracing
extended from just ['resistor','resistor-us'] to 9 two-terminal
passives with per-part pin name maps
- New CI workflow test-circuit.yml runs the sandbox on push/PR
- frontend-tests.yml regenerates metadata and fails if committed
JSON is stale
- Documented 2 new ngspice gotchas in circuit-emulation-gotchas.md:
unicode in netlist titles silently hangs the parser, and
MOSFET Level=3 + W=0.1m causes .op to hang
- 164/164 sandbox tests passing in ~9 s (was 88 pre-fase-9)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 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.
- Created a new DocsPage component for project documentation with links to GitHub and Discord.
- Added Arduino sketch for serial communication test between Raspberry Pi and Arduino.
- Implemented avr_runner.js to emulate ATmega328P and bridge serial communication over TCP.
- Developed a Python test script to validate the serial integration between the emulated Raspberry Pi and Arduino.
- Added LogicGateParts.ts for simulating various logic gates (AND, NAND, OR, NOR, XOR, NOT).
- Introduced ProtocolParts.ts for simulating I2C and SPI components including SSD1306 OLED, DS1307 RTC, MPU6050 IMU, DHT22 sensor, HX711 load cell, IR receiver, IR remote, and MicroSD card.
- Implemented BasicParts.ts with a membrane keypad and rotary dialer simulations.
- Enhanced SensorParts.ts with a single NeoPixel and PIR motion sensor.
- Updated index.ts to include new parts for logic gates and protocols.
- Modified vite-env.d.ts to declare new custom elements for the added components.
- 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.