Browser Emulator¶
The Cyber Fidget browser emulator lets you run real app code directly in your browser — no hardware required. It compiles your C++ app to WASM and maps every hardware feature (OLED, buttons, slider, LEDs, audio) to browser equivalents.
Who is this for?
- App developers: Test your code instantly without flashing a device
- Newcomers: Try Cyber Fidget apps before buying hardware
- App Builder users: See your generated app running in seconds
Where to find it¶
The emulator lives inside the App Builder at cyberfidget.com/build. Use the action bar to Compile Emulator (builds your code to WASM) and Emulator (runs the last build from cache).
Screenshot

Quick Start¶
flowchart LR
subgraph You
A[Open App Builder] --> B[Write or generate app]
B --> C[Click Compile Emulator]
C --> D[Click Emulator]
end
subgraph System
C --> E[GitHub Actions builds WASM]
E --> F[Download + cache in IndexedDB]
F --> D
D --> G[App runs in browser]
end
1. Open the App Builder¶
Go to cyberfidget.com/build and sign in with GitHub.
2. Write or Generate an App¶
Use the wizard to generate an app, import an existing one, or write code directly in the editors.
3. Compile¶
Click the Compile Emulator button below the serial terminal. This sends your code to GitHub Actions on your own fork of the firmware repo, compiles it to WASM, and downloads the result. Takes about 1–2 minutes the first time.
First time setup
You need a GitHub account and a fork of the CyberFidget firmware repo. The App Builder walks you through forking automatically when you sign in.
4. Run¶
Click the Emulator button (play icon) in the action bar. Your app loads from cache and runs immediately.
How the emulator fits together¶
flowchart TB
subgraph Browser
UI[Device mockup: canvas, buttons, slider, LEDs]
Bridge[wasm_bridge.js: loads WASM, wires events]
WASM[Your app.wasm + loader.js]
UI <--> Bridge
Bridge <--> WASM
end
subgraph Build
Code[Your .h + .cpp]
Code -->|Emscripten| WASM
end
The on-screen device (OLED, buttons, slider, LEDs) is driven by the same C++ app that would run on real hardware. The HAL (Hardware Abstraction Layer) is swapped for browser APIs so no ESP32 is involved.
Emulator Controls¶
The emulator mimics the physical Cyber Fidget layout:
flowchart LR
subgraph Inputs
B1[Top Left Q]
B2[Top Right E]
B3[Middle Left A]
B4[Middle Right D]
B5[Bottom Left Z]
B6[Bottom Right C]
S[Slider]
end
subgraph Device
OLED[128×64 OLED]
LED[4 LEDs]
end
B1 & B2 & B3 & B4 & B5 & B6 --> Device
S --> Device
Device --> OLED
Device --> LED
| Physical Control | Emulator Equivalent | Keyboard Shortcut |
|---|---|---|
| Top Left button | Click Top Left button | Q |
| Top Right button | Click Top Right button | E |
| Middle Left button | Click Middle Left button | A |
| Middle Right button | Click Middle Right button | D |
| Bottom Left button | Click Bottom Left button | Z |
| Bottom Right button | Click Bottom Right button | C |
| Slider (potentiometer) | Vertical slider on the left | Drag |
| OLED display (128×64) | Canvas at top | — |
| 3 front LEDs + 1 back LED | Colored circles | — |
Screenshot (optional)
Add a screenshot of the emulator device mockup with labels for OLED, buttons, slider, and LEDs. Save as docs/assets/emulator/device-mockup.png.
Serial Monitor¶
Below the emulator, a Serial Monitor panel shows any Serial.println() output from your app — useful for debugging.
How Compilation Works¶
When you click Compile Emulator, the following happens:
sequenceDiagram
participant You
participant AppBuilder
participant GitHub
participant Browser
You->>AppBuilder: Click Compile Emulator
AppBuilder->>AppBuilder: Base64-encode .h and .cpp
AppBuilder->>GitHub: workflow_dispatch on your fork
GitHub->>GitHub: Emscripten builds WASM
GitHub->>GitHub: Upload artifacts
AppBuilder->>GitHub: Poll run, download artifact ZIP
AppBuilder->>Browser: Store .js + .wasm in IndexedDB
You->>AppBuilder: Click Emulator
AppBuilder->>Browser: Load from IndexedDB, run WASM
- Your
.hand.cppcode is base64-encoded - A GitHub Actions workflow is triggered on your fork of the firmware repo
- The workflow compiles your code with Emscripten (a C++ to WebAssembly compiler)
- The compiled
.jsand.wasmfiles are uploaded as build artifacts - The App Builder downloads and caches them in your browser (using IndexedDB)
Compilation runs on YOUR GitHub
Compiling uses your GitHub Actions minutes, not CyberFidget's. This keeps the service free and sustainable. Pre-built official apps are cached and don't require compilation.
Build Cache¶
- Compiled WASM is cached in your browser's IndexedDB
- Clicking Emulator loads from cache instantly — no recompilation
- Cache persists across page refreshes
- Clicking Compile Emulator always triggers a fresh build
- Clicking Start Fresh clears the cache
What Works in the Emulator¶
| Feature | Status | Notes |
|---|---|---|
| OLED display (128×64) | Full | Pixel-perfect with real firmware font rendering |
| All 6 buttons | Full | Click or use keyboard shortcuts |
| Slider | Full | Maps to the same 0–4095 ADC range as hardware |
| RGBW LEDs (4) | Full | Colors rendered with glow effects; dim values boosted for visibility |
| Serial output | Full | Routed to the Serial Monitor panel |
| Audio/tones | Partial | Basic tone generation via Web Audio API |
| Accelerometer | Stub | Returns constant values (no tilt/shake detection) |
| Battery level | Stub | Always reports 100% |
| WiFi | Stub | Not available in browser |
| Deep sleep | Stub | No-op (calls are safely ignored) |
Tips¶
- Test with keyboard shortcuts —
Q/E/A/D/Z/Cfor buttons is faster than clicking - Watch the serial terminal — If your app isn't behaving right, add
Serial.println()calls for debugging - LED values are boosted — The emulator scales up dim LED values (below brightness 50) so they're visible on screen. On real hardware, even brightness 3/255 emits visible light, but
rgb(0, 3, 0)on a dark background is invisible - The slider is inverted — This matches the physical device orientation
Troubleshooting¶
"No build found. Click Compile first."¶
You haven't compiled yet, or the code changed since the last compile. Click Compile Emulator.
Compilation takes too long (>5 minutes)¶
Check your fork's Actions tab on GitHub. The workflow may have failed or be queued behind other jobs. If the run failed, open the run and read the log for errors (e.g. missing wasm/ directory, CMake or Emscripten errors).
"Sign in to GitHub to compile your app"¶
The emulator needs a GitHub token to trigger compilation on your fork. Sign in using the GitHub button in the top right. If you're already signed in, try signing out and back in; the token may have expired.
Workflow fails with "wasm/CMakeLists.txt not found"¶
Your fork may be out of date or missing the WASM build files. Sync your fork with the upstream CyberFidget firmware repo so that the wasm/ directory and .github/workflows/compile-wasm.yml exist.
Artifact download fails or "Failed to fetch artifact"¶
GitHub Actions artifacts are only available for a limited time after the run. If you waited too long, run Compile Emulator again. If it fails immediately, check your network and that GitHub isn't blocking the request (e.g. corporate firewall).
App compiles but doesn't run / blank screen¶
- Open the browser dev tools (F12) and check the Console for errors (e.g. "CyberFidgetModule is not a function", WASM compile errors).
- Ensure your app has proper
begin()andupdate()methods and that the app is selected correctly in the build (e.g. custom app name matches). - Try Start Fresh and then Compile Emulator again to clear a bad cache.
App compiles but doesn't behave right¶
- Check the Serial Monitor for
Serial.println()output or error messages. - The emulator runs at 50 FPS — same as the real device; timing should match.
- If only some features fail (e.g. display works but LEDs don't), see the Emulator Dev Guide for known HAL behavior.
LEDs appear dim or the wrong color¶
LED channel behavior in the emulator matches the firmware's Adafruit NeoPixel shim (WRGB packing). If colors look different from hardware, the firmware's RGBController may have intentional channel adjustments for the specific LED hardware on the device.
"CORS" or "file://" errors when loading WASM¶
WASM cannot be loaded from file:// URLs. You must use the App Builder on the live site (or a local HTTP server). If you're building WASM locally, serve the built files over HTTP and load them via the site's "Load from file" option if available.
Buttons or slider don't respond¶
Make sure the emulator panel has focus or click once inside it. Keyboard shortcuts (Q/E/A/D/Z/C) only work when the page (or the emulator area) has focus. If you're on a tablet or phone, use the on-screen buttons.
Serial Monitor is empty¶
Your app may not be calling Serial.println(). Add a line in begin() or update() to confirm the app is running. If you see output once then it stops, the app may have crashed or entered an infinite loop; check the browser console.
Different browser or device: cache not there¶
The IndexedDB cache is per-origin and per-browser. Compiling on your laptop won't populate the cache on your phone or another browser. Run Compile Emulator on each device/browser where you want to run the app.
I want to run completely offline¶
Right now compilation requires GitHub Actions (internet). For fully offline use, you need to build WASM locally with Emscripten and load the resulting files; see the Emulator Dev Guide (Local Development) and the follow-up plan for offline compilation.