Ioruba transforms an Arduino Nano + 3 knobs into a tactile desktop control deck. The active product path is a Tauri 2 + React + TypeScript app backed by Rust for system-audio operations and Arduino C++ firmware for the physical controller.
Current platform status Real audio control is implemented for Linux through
pactl. macOS and Windows builds are still useful for UI review, packaging checks, and demo mode, but they do not provide a production-ready audio backend yet.
Releases · Quick Start · Hardware Setup · Nano Setup · Profile Examples · Support · Testing · Contributing · Funding · Roadmap
📸 Until a fresh capture of the current Tauri app is published, the archived screen above remains a useful visual reference for the product's tactile dashboard direction.
The project keeps the hardware feel of a small mixer while modernizing the software stack that drives it:
- the active desktop runtime lives in
apps/desktop - the firmware is consolidated in
firmware/arduino/ioruba-controller - shared protocol and runtime logic live in
packages/shared - the Linux audio backend was rewritten in Rust using
pactl - persistence moved from split YAML/UI state to a local JSON profile model
- migration history and parity notes now live in
docs/migration - one archived Python/GTK prototype is still kept under
legacy/
- serial packets such as
512|768|1023 - firmware handshake metadata with board name, firmware version, protocol version, and knob count
- compatibility with the legacy packet format
P1:512 - live telemetry and a persistent watch log inside the desktop app
- editable JSON profiles stored in the app config directory
- demo mode for UI validation without touching system audio
- Linux audio target handling for
master,application,source, andsink - CI for desktop/shared validation plus firmware compilation
- tagged release workflows for desktop bundles and firmware artifacts
| Platform | Status | Notes |
|---|---|---|
| Linux | Supported | Main production path: serial workflow, pactl audio backend, demo mode, and hardware validation |
| macOS | Partial | Desktop shell and demo-mode validation are useful; real audio control is not implemented |
| Windows | Partial | Desktop shell and demo-mode validation are useful; real audio control is not implemented |
The shipped default profile is intentionally simple and can be edited from the app's JSON configuration panel:
| Knob | Default label | Target |
|---|---|---|
| 1 | Master Volume |
Default output volume |
| 2 | Applications |
Spotify, Google Chrome, and Firefox |
| 3 | Microphone |
default_microphone |
Install dependencies and validate the active stack:
npm install
npm run verifyCompile the firmware for the current controller sketch:
npm run firmware:compileRun the desktop app:
npm run desktop:dev
npm run desktop:watchnpm run desktop:devstarts the frontend onlynpm run desktop:watchstarts the full Tauri desktop shell
If you are setting up real hardware, follow these guides next:
- QUICKSTART.md for the end-to-end Linux workflow
- NANO_SETUP.md for board flashing and serial checks
- docs/guides/hardware-setup.md for wiring the physical controller
- docs/guides/profile-examples.md for ready-to-paste JSON profiles
| Command | What it does |
|---|---|
npm run verify |
Runs shared + desktop typecheck, shared + desktop tests, Rust tests, and the desktop production build |
npm run desktop:dev |
Starts the Vite frontend for UI work |
npm run desktop:watch |
Starts the full Tauri desktop app in development |
npm run desktop:icons |
Regenerates every desktop icon asset from apps/desktop/src-tauri/icons/app-icon.svg |
npm run desktop:tauri:build |
Builds the Tauri desktop app locally without bundling installers |
npm run firmware:compile |
Compiles the Arduino Nano firmware |
npm run rust:test |
Runs Rust backend tests |
npm run rust:audit |
Audits the Rust lockfile while accounting for the local glib backport |
| Path | Purpose |
|---|---|
apps/desktop |
Tauri 2 desktop app, React UI, Zustand state, and telemetry dashboards |
apps/desktop/src-tauri |
Rust commands for persistence, watch logging, and Linux audio control |
packages/shared |
Shared domain types, defaults, runtime math, and protocol parsing |
firmware/arduino/ioruba-controller |
Arduino firmware for Nano-compatible boards |
docs/guides |
Practical setup guides |
docs/migration |
Migration planning and parity audit material |
legacy |
Archived Python/GTK prototype and small historical leftovers |
The app stores its runtime files in the platform config directory:
- watch log:
ioruba-watch.log - active profile state:
ioruba-state.json
Typical locations:
- Linux:
~/.config/io.ioruba.desktop/ - macOS:
~/Library/Application Support/io.ioruba.desktop/ - Windows:
%APPDATA%\\io.ioruba.desktop\\
The watch log is trimmed automatically to roughly 1 MiB, so it stays useful for diagnostics without growing forever.
When you edit apps/desktop/src-tauri/icons/app-icon.svg, regenerate the desktop, Android, iOS, icns, and ico assets with:
npm run desktop:iconsThat command rewrites the generated files under apps/desktop/src-tauri/icons.
The current Linux Tauri stack still resolves through GTK3 glib 0.18.x, so the repository carries a local backport of GHSA-wrw7-89jp-8q8g under apps/desktop/src-tauri/vendor/glib-0.18.5 until upstream moves. Use the following command to audit the current lockfile with that backport in mind:
npm run rust:audit| Document | Use it when you need... |
|---|---|
| docs/guides/profile-examples.md | Real JSON profile samples and Linux target matching rules |
| QUICKSTART.md | The fastest path from zero to a running app |
| NANO_SETUP.md | Flashing and validating the Arduino Nano |
| docs/guides/hardware-setup.md | Physical wiring and assembly |
| docs/debug/support.md | A support playbook for serial, audio, and profile-debug issues |
| TESTING.md | Automated checks, smoke tests, and release validation |
| docs/migration/logic-audit.md | Parity coverage with archived implementations |
The repository still keeps one archived implementation for historical reference:
legacy/arduino-audio-controller
Deeper migration context lives in docs/migration. The active product surface lives in apps/desktop, packages/shared, and firmware/arduino/ioruba-controller.
MIT
