HOST
Browser
UI, JavaScript, Web Serial and the Wanix namespace.
window + WebAssembly
WANIX FIELD KIT · LAB 01 · ESP8266
Build a complete microcontroller application inside a Linux machine that exists inside this browser tab—then carry it across USB into the physical world. There is no application backend or remote build service: the host serves only static files, while your source, Linux VM, compiler job and firmware all stay inside your browser.
THE BIG IDEA
Wanix is the connective tissue. It gives a web page Unix-like namespaces, files, tasks, terminals and virtual machines, so existing command-line tools can become parts of a local-first web application. The web host only delivers static assets; every active step runs on this device.
HOST
UI, JavaScript, Web Serial and the Wanix namespace.
window + WebAssembly
GUEST
Alpine in v86 runs the real 32-bit Xtensa toolchain.
gcc → ld → elf2bin
TARGET
Your selected ESP8266 development board runs the code and blinks its LED.
80 MHz · 4 or 16 MiB flash
THE RUNTIME MAP
The page coordinates three instruction sets and two hard boundaries. “Local” does not mean everything runs in one JavaScript process.
Browser host JavaScript + Wanix WebAssembly
│ files and terminal bytes
▼
v86 guest x86 Linux + Xtensa cross-compiler
│ firmware.bin over Web Serial
▼
ESP8266 target physical Xtensa microcontroller
Wanix gives the browser Unix-shaped ways to connect these components: mounted resources, paths, tasks and byte streams. The network only fetches static HTML, JavaScript, WebAssembly and toolchain archives; it never receives your generated source, shell commands, compiler output or firmware.
COMPOSE THE COMPUTER
The page does not install a Linux machine in the usual sense. These binds layer remote archives, temporary browser memory and a VM device into one namespace.
/ ├── opt/xtensa-lx106 compiler archive ├── opt/esp8266 Arduino SDK + core ├── workspace → #ramfs/new │ ├── main.cpp ← browser writes │ └── build.sh ← HTTP file bind └── vm → #vm └── v86 ← emulator archive
Attach a resource at a path. It can come from HTTP, RAM, persistent browser storage or a device.
A private view of the filesystem assembled for this application—not the host Mac’s filesystem.
<wanix-bind dst="." type="archive"
src="wanix-linux.tgz">
<wanix-bind dst="workspace"
src="#ramfs/new">
<wanix-bind dst="vm" src="#vm">
NAMESPACE COMPOSITION
<wanix-namespace> creates a private root. Each child bind places a resource provider at a destination path, so unrelated implementations appear as one coherent tree.
<wanix-bind dst="." type="archive" src="wanix-linux.tgz">
<wanix-bind dst="workspace" src="#ramfs/new">
<wanix-bind dst="vm" src="#vm">
<wanix-vm export="ttyS0" mem="256M" term start>
/opt/xtensa-lx106.#ramfs/new supplies a browser-memory filesystem at /workspace. JavaScript and the guest both see its files.#vm supplies the virtual-machine device. The v86 archive adds its driver, and <wanix-vm> boots the guest.#task path before enabling Build. Files appearing in the tree are the readiness signal.A path describes where a capability appears, not where its bytes physically live. HTTP archives, RAM and a device can all participate in the same namespace.
MAKE IT YOURS
This is not a configuration block bolted onto a cached application. Your choices become C++ source, and Wanix builds a new application and firmware image.
SOURCE GENERATION
Every input event calls firmwareSource(owner, cycleMs, profile). The source panel is therefore a preview of the exact text that will become /workspace/main.cpp.
constexpr char kOwner[] = "Jeff";
constexpr uint32_t kBlinkHalfPeriodMs = 500;
digitalWrite(LED_BUILTIN, LOW); // LED on
delay(kBlinkHalfPeriodMs);
digitalWrite(LED_BUILTIN, HIGH); // LED off
LOW turns it on.main.cpp, then links a new ELF and packages a new flash image.The UI is a source-code authoring tool. Personalization is not patched into a prebuilt firmware blob; it crosses the browser/guest boundary as an ordinary file.
CROSS THE VM BOUNDARY
No build request is sent to a server. JavaScript writes the source into the shared namespace, opens the VM terminal as a file, sends one shell command and watches for the result to appear back in the tree.
TERMINAL-DRIVEN BUILD
JavaScript treats the VM terminal as a duplex file. It writes a shell command to the same byte stream from which it reads compiler output.
const out = await root.openReadable(`${vm.term}/data`);
const input = await root.openWritable(`${vm.term}/data`);
BUILD_ID=build-… APP_SOURCE=/workspace/main.cpp \
/bin/sh /workspace/build.sh
workspace/main.cpp through the Wanix root API.xtensa-lx106-elf-g++, links it with the packaged Arduino core and SDK, then runs wanix-elf2bin./tmp tmpfs; only useful outputs cross back into the shared workspace.result.json.Automation and a person can drive the same real shell interface. The application composes familiar files and commands instead of requiring a custom guest API.
RETURN TO THE BROWSER
The guest writes firmware.bin into the shared workspace. Wanix lets browser JavaScript read it directly: nothing is uploaded, and no application server sees the source, compiler transcript or firmware.
firmware.bin
— flashable bytesfirmware.elf
— linked executableSHA-256
Build to calculate content identityNo artifact yet. The entire application will be written from offset zero.
ARTIFACT HANDOFF
The guest copies its result files into a unique directory below /workspace/artifacts. Because that path is backed by Wanix RAM, browser JavaScript can immediately consume the same bytes.
await root.waitFor("workspace/artifacts/build-…/result.json");
const firmware = await root.readFile("…/firmware.bin");
const digest = await crypto.subtle.digest("SHA-256", firmware);
const url = URL.createObjectURL(new Blob([firmware]));
result.json carries build status, elapsed guest time and exact source, ELF and firmware byte counts.readFile returns the binary firmware to JavaScript as bytes—not base64 and not an HTTP response.firmware.bin is the ESP8266 flash layout that starts at offset zero.The build result is not returned by a service call. Producer and consumer agree on paths, so a Linux process and a web component can exchange artifacts through files.
OPEN THE MACHINE
wanix-term attaches an xterm directly to the same terminal device the build controller used. This is the actual Alpine guest, with the same namespace and files—not a transcript or simulated shell.
The UI opens #term/…/data for reading and writing. That same file can serve automation first and an interactive human next.
TRY THESE INSIDE LINUX
pwd
ls -lah /workspace
sed -n '1,80p' /workspace/main.cpp
find /opt -maxdepth 2 -type d
xtensa-lx106-elf-g++ --version
find /workspace/artifacts -type f
The shell becomes available when the Wanix VM is ready.
A TERMINAL AS A FILE
<wanix-term> is an xterm UI attached to the VM’s terminal path. It does not imitate a shell; keyboard bytes go to Linux and terminal bytes come back.
const term = document.createElement("wanix-term");
term.setAttribute("for", "linux");
term.setAttribute("path", vm.term);
term.setAttribute("raw", "");
term.setAttribute("scrollback", "2000");
#term/…/data.A terminal is another namespaced resource. The same endpoint supports a polished web interface, scripted control and direct human inspection without inventing three different backends.
ENTER THE PHYSICAL WORLD
Wanix produces the bytes; ESP Web Tools asks the browser for a serial port. The chooser and confirmation require you because a web page must not silently rewrite attached hardware.
Next action Connect your board over USB, then let the browser choose it and install your new firmware.
This lab targets a Wemos D1 mini Pro with an ESP8266 and 16 MiB flash. Installation replaces the application at offset 0x000000.
THE HARDWARE BOUNDARY
After a successful build, the page creates an ESP Web Tools manifest that identifies the target family and maps the firmware Blob URL onto flash address 0x000000.
{
"builds": [{
"chipFamily": "ESP8266",
"parts": [{ "path": "blob:…", "offset": 0 }]
}]
}
Wanix gets an existing native toolchain to the artifact boundary. A browser-native component can then carry that artifact into hardware while preserving the browser’s explicit permission model.