An AVR8js and Wokwi Elements playground implemented with Electron
TypeScript
58
105 commits
updated Mar 9, 2026
A full-featured Arduino simulator built with AVR8js, Wokwi Elements, and Electron. Write Arduino code, design circuits visually, and simulate everything in real time — all offline in a native desktop application.
See ROADMAP.md for the phased plan to expand the simulator and improve AVR8 architecture coverage, and BACKLOG.md for the prioritized execution backlog.
.chip.c/.cpp + .chip.json + .chip.wasm) inside the simulator| Category | Components |
|---|---|
| Boards | Arduino Uno, Nano, Mega |
| Output | LED, RGB LED, Buzzer, Relay, LED Bar Graph, 7-Segment, Servo, Stepper Motor |
| Display | LCD 1602 (I2C), LCD 2004 (I2C), SSD1306 OLED (I2C), ILI9341, NeoPixel, NeoPixel Matrix, LED Ring |
| Input | Pushbutton, Pushbutton 6mm, Slide Switch, Tilt Switch, DIP Switch 8, Membrane Keypad, Rotary Encoder (KY-040), Rotary Dialer, Analog Joystick |
| Analog | Potentiometer, Slide Potentiometer |
| Sensors | DHT22, HC-SR04, NTC Temperature, Photoresistor, Flame, Big/Small Sound, PIR Motion, Heart Beat, Gas Sensor, MPU6050, HX711 |
| Communication | IR Receiver, IR Remote, DS1307 RTC, microSD Card |
| Passive | Resistor |
All wired connections in diagram.json are automatically routed between Arduino pins and components:
0x27)0x27)0x3C, 0x3D)0x68).chip.c/.cpp + .chip.json) into WASM and run them inside the simulatorBuild Chips command (F6) plus automatic chip build before sketch compile (F5)File convention
mychip.chip.json (manifest)mychip.chip.c or mychip.chip.cpp (source)mychip.chip.wasm (generated artifact)Supported runtime ABI (MVP)
chip_init(), chip_tick(), chip_dispose()millis/avr8js_millis, micros/avr8js_microsavr8js_gpio_read(pin), avr8js_gpio_write(pin, value), avr8js_gpio_mode(pin, mode)chip_i2c_connect, chip_i2c_read, chip_i2c_write, chip_i2c_disconnectchip_control_set/get (or aliases chip_set_control/get_control)Build backends
external (default): command template in Settings (default: clang --target=wasm32 -O2 -nostdlib -Wl,--no-entry -Wl,--export-all -Wl,--allow-undefined -o "{{OUTPUT}}" "{{SOURCE}}")embedded-experimental: renderer-side embedded pipeline with fallback and support for:
// @wasm-base64 <...> test directive in *.chip.c/*.chip.cpp<name>.chip.wasm from project files (with validation)Current limitations
.avr8js JSON bundles| Technology | Version | Purpose |
|---|---|---|
| Electron | 40.6.0 | Desktop shell |
| React | 19.2 | UI framework |
| TypeScript | 5.9 | Type safety |
| Vite | 7 | Build tool & bundler |
| avr8js | 0.21.0 | ATmega328p CPU emulator |
| @wokwi/elements | 1.9.2 | Circuit component web elements |
| Monaco Editor | 0.55.1 | Code editor |
| Zustand | 5 | State management |
| Tailwind CSS | 3.4 | Styling |
| Split.js | 1.6 | Resizable panels |
| Lucide React | 0.575 | Icon library |
| ESLint | 9 | Linting (0 errors) |
| Vitest | 4 | Testing |
# Clone the repository
git clone https://github.com/arcostasi/avr8js-electron.git
cd avr8js-electron
# Install dependencies
npm install
# Development (build + launch)
npm run dev
# Or build and start manually
npm run build
npm start
| Script | Description |
|---|---|
npm run dev | Build and launch in development mode |
npm run build | Compile TypeScript + Vite build |
npm run watch | Run the TypeScript compiler in watch mode |
npm start | Launch the Electron app |
npm test | Run the Vitest suite |
npm run test:perf-smoke | Run loose performance smoke checks for discovery/load/parse/netlist |
npm run lint | Run ESLint on all source files |
npm run lint:fix | Auto-fix lint issues |
The repository includes a lightweight smoke benchmark for the main hot paths in the app:
Run it locally with:
npm run test:perf-smoke
The thresholds are intentionally loose and meant to catch obvious regressions, not replace profiling.
avr8js-electron/
├── index.html # Electron renderer entry
├── vite.config.ts # Vite build configuration
├── tsconfig.json # TypeScript configuration
├── eslint.config.mjs # ESLint flat config
├── tailwind.config.cjs # Tailwind CSS configuration
├── examples/ # Built-in simulator examples and custom-chip demos
├── src/
│ ├── main/ # Electron main process
│ │ ├── main.ts # Window creation, IPC handlers, storage and project IPC
│ │ ├── project-io.ts # Async project discovery/load/import/export services
│ │ └── *.test.ts # Main-process tests and perf smoke checks
│ ├── electron/ # IPC infrastructure
│ │ ├── ipc-app.ts # App bootstrap
│ │ ├── ipc-channel.ts # Channel interface
│ │ ├── ipc-request.ts # Request types
│ │ ├── ipc-service.ts # Service base class
│ │ └── info-channel.ts # System info channel
│ ├── renderer/ # React UI (renderer process)
│ │ ├── App.tsx # Root component
│ │ ├── index.tsx # React mount point
│ │ ├── index.css # Global styles
│ │ ├── components/
│ │ │ ├── Editor.tsx # Monaco code editor
│ │ │ ├── PerformancePanel.tsx
│ │ │ ├── ProjectSidebar.tsx
│ │ │ ├── SerialMonitor.tsx
│ │ │ └── simulator/
│ │ │ ├── WokwiSimulator.tsx
│ │ │ ├── PartRenderer.tsx
│ │ │ ├── SimulatorToolbar.tsx
│ │ │ ├── AddComponentMenu.tsx
│ │ │ ├── CanvasZoomControls.tsx
│ │ │ ├── PinOverlay.tsx
│ │ │ ├── PinTooltip.tsx
│ │ │ ├── WireLayer.tsx
│ │ │ ├── WireColorPopup.tsx
│ │ │ └── ComponentPropertyEditor.tsx
│ │ ├── hooks/
│ │ │ ├── useSimulation.ts
│ │ │ ├── useDiagramState.ts # Undo/redo history
│ │ │ ├── useAutoSave.ts
│ │ │ ├── useCanvasInteraction.ts
│ │ │ ├── usePinPositions.ts
│ │ │ ├── useResizableLayout.ts
│ │ │ └── useWireRenderer.tsx
│ │ ├── services/
│ │ │ ├── app-session.ts # Session snapshot/restore helpers
│ │ │ ├── chip-build-cache.ts
│ │ │ ├── chip-build-diagnostics.ts
│ │ │ ├── chip-build-embedded.ts
│ │ │ ├── custom-chips.ts
│ │ │ ├── gpio-router.ts
│ │ │ ├── netlist-builder.ts
│ │ │ ├── perf-dashboard.ts
│ │ │ ├── perf-panel-storage.ts
│ │ │ ├── project-export.ts
│ │ │ ├── project-loader.ts
│ │ │ ├── renderer-persist.ts
│ │ │ ├── simulation-engine.ts
│ │ │ └── ui-session.ts
│ │ ├── store/
│ │ │ ├── projectStore.ts
│ │ │ └── settingsStore.ts
│ │ ├── constants/
│ │ │ └── wokwi-components.ts # 49 component catalog
│ │ ├── types/
│ │ │ ├── editor-diagnostics.ts
│ │ │ └── wokwi.types.ts # Diagram schema + V1→V2 migration
│ │ └── utils/
│ │ ├── catenary.ts # Wire physics
│ │ ├── perf.ts # Performance event stream and helpers
│ │ └── pin-mapping.ts # Arduino pin → AVR port mapping
│ └── shared/ # AVR simulation core
│ ├── execute.ts # AVRRunner (CPU lifecycle)
│ ├── compile.ts # Cloud hex compilation
│ ├── adc-registry.ts # ADC channel management
│ ├── i2c-bus.ts # I2C device multiplexer
│ ├── lcd1602.ts # LCD 16x2 controller
│ ├── lcd2004.ts # LCD 20x4 controller
│ ├── ssd1306.ts # SSD1306 OLED controller
│ ├── ws2812.ts # WS2812/NeoPixel controller
│ ├── dht22.ts # DHT22 sensor controller
│ ├── hc-sr04.ts # HC-SR04 ultrasonic controller
│ ├── ds1307.ts # DS1307 RTC controller
│ ├── ir.ts # NEC IR protocol
│ ├── speaker.ts # Speaker/buzzer audio
│ ├── stepper.ts # Stepper motor controller
│ ├── eeprom.ts # EEPROM persistence
│ ├── intelhex.ts # Intel HEX parser
│ ├── format-time.ts # Time formatting utility
│ ├── cpu-performance.ts # FPS/speed measurement
│ └── task-scheduler.ts # Cooperative task scheduler
The examples/ folder contains a broad set of working sketches and circuit demos, including:
| Example | Description |
|---|---|
hello-world | Classic LED blink starting point |
7segment, lcd2004, ssd1306, ili9341 | Display-oriented examples |
neopixel, neopixel-matrix, matrix8x8, matrix16x16, led-ring | LED matrix and addressable LED demos |
servo, stepper-motor, buzzer, relay-module | Actuator and output device examples |
dht22, hc-sr04, hx711, mpu6050, pir-motion, photoresistor | Sensor integrations |
microsd-card, ds1307, ir-receiver | Communication and peripheral examples |
custom-chip-* | Custom chip API and runtime bridge demonstrations |
Every bundled example is intended to stay functional and directly runnable inside the app.
| Example | Main ABI / APIs Demonstrated |
|---|---|
custom-chip-gpio | pin_mode, pin_read, pin_write, control bridge (chip_control_set/get) |
custom-chip-framebuffer | framebuffer_init, buffer_write |
custom-chip-analog | pin_dac_write, pin_write |
custom-chip-time | millis, micros |
custom-chip-uart | uart_init, uart_write |
custom-chip-i2c | chip_i2c_connect, chip_i2c_read, chip_i2c_write, chip_i2c_disconnect |
custom-chip-spi | spi_init, spi_start |
custom-chip-attributes | attr_init, attr_read |
When using the Electron or other GitHub logos, be sure to follow the GitHub logo guidelines.
An AVR8js and Wokwi Elements playground implemented with Electron
TypeScript
58
105 commits
updated Mar 9, 2026
A full-featured Arduino simulator built with AVR8js, Wokwi Elements, and Electron. Write Arduino code, design circuits visually, and simulate everything in real time — all offline in a native desktop application.
See ROADMAP.md for the phased plan to expand the simulator and improve AVR8 architecture coverage, and BACKLOG.md for the prioritized execution backlog.
.chip.c/.cpp + .chip.json + .chip.wasm) inside the simulator| Category | Components |
|---|---|
| Boards | Arduino Uno, Nano, Mega |
| Output | LED, RGB LED, Buzzer, Relay, LED Bar Graph, 7-Segment, Servo, Stepper Motor |
| Display | LCD 1602 (I2C), LCD 2004 (I2C), SSD1306 OLED (I2C), ILI9341, NeoPixel, NeoPixel Matrix, LED Ring |
| Input | Pushbutton, Pushbutton 6mm, Slide Switch, Tilt Switch, DIP Switch 8, Membrane Keypad, Rotary Encoder (KY-040), Rotary Dialer, Analog Joystick |
| Analog | Potentiometer, Slide Potentiometer |
| Sensors | DHT22, HC-SR04, NTC Temperature, Photoresistor, Flame, Big/Small Sound, PIR Motion, Heart Beat, Gas Sensor, MPU6050, HX711 |
| Communication | IR Receiver, IR Remote, DS1307 RTC, microSD Card |
| Passive | Resistor |
All wired connections in diagram.json are automatically routed between Arduino pins and components:
0x27)0x27)0x3C, 0x3D)0x68).chip.c/.cpp + .chip.json) into WASM and run them inside the simulatorBuild Chips command (F6) plus automatic chip build before sketch compile (F5)File convention
mychip.chip.json (manifest)mychip.chip.c or mychip.chip.cpp (source)mychip.chip.wasm (generated artifact)Supported runtime ABI (MVP)
chip_init(), chip_tick(), chip_dispose()millis/avr8js_millis, micros/avr8js_microsavr8js_gpio_read(pin), avr8js_gpio_write(pin, value), avr8js_gpio_mode(pin, mode)chip_i2c_connect, chip_i2c_read, chip_i2c_write, chip_i2c_disconnectchip_control_set/get (or aliases chip_set_control/get_control)Build backends
external (default): command template in Settings (default: clang --target=wasm32 -O2 -nostdlib -Wl,--no-entry -Wl,--export-all -Wl,--allow-undefined -o "{{OUTPUT}}" "{{SOURCE}}")embedded-experimental: renderer-side embedded pipeline with fallback and support for:
// @wasm-base64 <...> test directive in *.chip.c/*.chip.cpp<name>.chip.wasm from project files (with validation)Current limitations
.avr8js JSON bundles| Technology | Version | Purpose |
|---|---|---|
| Electron | 40.6.0 | Desktop shell |
| React | 19.2 | UI framework |
| TypeScript | 5.9 | Type safety |
| Vite | 7 | Build tool & bundler |
| avr8js | 0.21.0 | ATmega328p CPU emulator |
| @wokwi/elements | 1.9.2 | Circuit component web elements |
| Monaco Editor | 0.55.1 | Code editor |
| Zustand | 5 | State management |
| Tailwind CSS | 3.4 | Styling |
| Split.js | 1.6 | Resizable panels |
| Lucide React | 0.575 | Icon library |
| ESLint | 9 | Linting (0 errors) |
| Vitest | 4 | Testing |
# Clone the repository
git clone https://github.com/arcostasi/avr8js-electron.git
cd avr8js-electron
# Install dependencies
npm install
# Development (build + launch)
npm run dev
# Or build and start manually
npm run build
npm start
| Script | Description |
|---|---|
npm run dev | Build and launch in development mode |
npm run build | Compile TypeScript + Vite build |
npm run watch | Run the TypeScript compiler in watch mode |
npm start | Launch the Electron app |
npm test | Run the Vitest suite |
npm run test:perf-smoke | Run loose performance smoke checks for discovery/load/parse/netlist |
npm run lint | Run ESLint on all source files |
npm run lint:fix | Auto-fix lint issues |
The repository includes a lightweight smoke benchmark for the main hot paths in the app:
Run it locally with:
npm run test:perf-smoke
The thresholds are intentionally loose and meant to catch obvious regressions, not replace profiling.
avr8js-electron/
├── index.html # Electron renderer entry
├── vite.config.ts # Vite build configuration
├── tsconfig.json # TypeScript configuration
├── eslint.config.mjs # ESLint flat config
├── tailwind.config.cjs # Tailwind CSS configuration
├── examples/ # Built-in simulator examples and custom-chip demos
├── src/
│ ├── main/ # Electron main process
│ │ ├── main.ts # Window creation, IPC handlers, storage and project IPC
│ │ ├── project-io.ts # Async project discovery/load/import/export services
│ │ └── *.test.ts # Main-process tests and perf smoke checks
│ ├── electron/ # IPC infrastructure
│ │ ├── ipc-app.ts # App bootstrap
│ │ ├── ipc-channel.ts # Channel interface
│ │ ├── ipc-request.ts # Request types
│ │ ├── ipc-service.ts # Service base class
│ │ └── info-channel.ts # System info channel
│ ├── renderer/ # React UI (renderer process)
│ │ ├── App.tsx # Root component
│ │ ├── index.tsx # React mount point
│ │ ├── index.css # Global styles
│ │ ├── components/
│ │ │ ├── Editor.tsx # Monaco code editor
│ │ │ ├── PerformancePanel.tsx
│ │ │ ├── ProjectSidebar.tsx
│ │ │ ├── SerialMonitor.tsx
│ │ │ └── simulator/
│ │ │ ├── WokwiSimulator.tsx
│ │ │ ├── PartRenderer.tsx
│ │ │ ├── SimulatorToolbar.tsx
│ │ │ ├── AddComponentMenu.tsx
│ │ │ ├── CanvasZoomControls.tsx
│ │ │ ├── PinOverlay.tsx
│ │ │ ├── PinTooltip.tsx
│ │ │ ├── WireLayer.tsx
│ │ │ ├── WireColorPopup.tsx
│ │ │ └── ComponentPropertyEditor.tsx
│ │ ├── hooks/
│ │ │ ├── useSimulation.ts
│ │ │ ├── useDiagramState.ts # Undo/redo history
│ │ │ ├── useAutoSave.ts
│ │ │ ├── useCanvasInteraction.ts
│ │ │ ├── usePinPositions.ts
│ │ │ ├── useResizableLayout.ts
│ │ │ └── useWireRenderer.tsx
│ │ ├── services/
│ │ │ ├── app-session.ts # Session snapshot/restore helpers
│ │ │ ├── chip-build-cache.ts
│ │ │ ├── chip-build-diagnostics.ts
│ │ │ ├── chip-build-embedded.ts
│ │ │ ├── custom-chips.ts
│ │ │ ├── gpio-router.ts
│ │ │ ├── netlist-builder.ts
│ │ │ ├── perf-dashboard.ts
│ │ │ ├── perf-panel-storage.ts
│ │ │ ├── project-export.ts
│ │ │ ├── project-loader.ts
│ │ │ ├── renderer-persist.ts
│ │ │ ├── simulation-engine.ts
│ │ │ └── ui-session.ts
│ │ ├── store/
│ │ │ ├── projectStore.ts
│ │ │ └── settingsStore.ts
│ │ ├── constants/
│ │ │ └── wokwi-components.ts # 49 component catalog
│ │ ├── types/
│ │ │ ├── editor-diagnostics.ts
│ │ │ └── wokwi.types.ts # Diagram schema + V1→V2 migration
│ │ └── utils/
│ │ ├── catenary.ts # Wire physics
│ │ ├── perf.ts # Performance event stream and helpers
│ │ └── pin-mapping.ts # Arduino pin → AVR port mapping
│ └── shared/ # AVR simulation core
│ ├── execute.ts # AVRRunner (CPU lifecycle)
│ ├── compile.ts # Cloud hex compilation
│ ├── adc-registry.ts # ADC channel management
│ ├── i2c-bus.ts # I2C device multiplexer
│ ├── lcd1602.ts # LCD 16x2 controller
│ ├── lcd2004.ts # LCD 20x4 controller
│ ├── ssd1306.ts # SSD1306 OLED controller
│ ├── ws2812.ts # WS2812/NeoPixel controller
│ ├── dht22.ts # DHT22 sensor controller
│ ├── hc-sr04.ts # HC-SR04 ultrasonic controller
│ ├── ds1307.ts # DS1307 RTC controller
│ ├── ir.ts # NEC IR protocol
│ ├── speaker.ts # Speaker/buzzer audio
│ ├── stepper.ts # Stepper motor controller
│ ├── eeprom.ts # EEPROM persistence
│ ├── intelhex.ts # Intel HEX parser
│ ├── format-time.ts # Time formatting utility
│ ├── cpu-performance.ts # FPS/speed measurement
│ └── task-scheduler.ts # Cooperative task scheduler
The examples/ folder contains a broad set of working sketches and circuit demos, including:
| Example | Description |
|---|---|
hello-world | Classic LED blink starting point |
7segment, lcd2004, ssd1306, ili9341 | Display-oriented examples |
neopixel, neopixel-matrix, matrix8x8, matrix16x16, led-ring | LED matrix and addressable LED demos |
servo, stepper-motor, buzzer, relay-module | Actuator and output device examples |
dht22, hc-sr04, hx711, mpu6050, pir-motion, photoresistor | Sensor integrations |
microsd-card, ds1307, ir-receiver | Communication and peripheral examples |
custom-chip-* | Custom chip API and runtime bridge demonstrations |
Every bundled example is intended to stay functional and directly runnable inside the app.
| Example | Main ABI / APIs Demonstrated |
|---|---|
custom-chip-gpio | pin_mode, pin_read, pin_write, control bridge (chip_control_set/get) |
custom-chip-framebuffer | framebuffer_init, buffer_write |
custom-chip-analog | pin_dac_write, pin_write |
custom-chip-time | millis, micros |
custom-chip-uart | uart_init, uart_write |
custom-chip-i2c | chip_i2c_connect, chip_i2c_read, chip_i2c_write, chip_i2c_disconnect |
custom-chip-spi | spi_init, spi_start |
custom-chip-attributes | attr_init, attr_read |
When using the Electron or other GitHub logos, be sure to follow the GitHub logo guidelines.