Simon Willison documented porting the Möbius array programming language to the browser, leaning on WebAssembly and help from LLMs. Here’s a compact playbook you can reuse for your own language, CLI tool, or DSL.
Why WebAssembly for niche languages
WebAssembly (Wasm) lets you run near-native code safely in the browser with zero installs. That means instant demos, interactive docs, and shareable sandboxes that lower onboarding friction.
It also provides a stable target for C/C++ and many other toolchains, so you can bring decades of code to the web. See the MDN WebAssembly guide for a solid overview.
7-step porting checklist
- Map dependencies: List system calls, file I/O, threads, networking, and UI needs. Decide if you’ll target Emscripten (browser libs) or WASI (POSIX-like, fewer browser shims).
- Compile to Wasm: For C/C++, start with Emscripten. Use size flags (-Oz, LTO) and export only what you need.
- Optimize the binary: Run wasm-opt (e.g., -O3 –strip-debug) and serve with Brotli/Gzip.
- Wrap in a Worker: Instantiate Wasm inside a Web Worker. Wire stdin/stdout via postMessage for a responsive UI.
- Persist state: Use Emscripten’s IDBFS or the Origin Private File System (OPFS) to store programs, examples, and session history.
- Stream and lazy-load: Use WebAssembly.instantiateStreaming and split large assets (examples, docs) to keep first paint fast.
- Minimal UI first: Start with a text area + Run button/REPL, then layer in syntax highlighting and shareable URLs.
Where LLMs actually help
- Build flags and linker errors: Paste errors; ask for minimal Emscripten flags and exports needed.
- Glue code generation: Have it scaffold Worker wrappers, stdin/stdout pipes, and a tiny REPL loop.
- Porting tricky syscalls: Get suggestions to replace unsupported APIs with browser-friendly patterns.
- Docs and examples: Draft quickstart guides and sample programs to validate the port.
Performance and UX tips
- Right-size INITIAL_MEMORY and enable growth to avoid long cold starts.
- Keep main thread free; heavy work lives in a Worker. If graphical, use OffscreenCanvas.
- Ship a tiny demo by default; lazy-load the rest. Measure with the Performance panel.
Common pitfalls
- Unsupported APIs: Replace sockets, blocking I/O, or fork/exec with browser-safe patterns.
- Licensing: Ensure you can redistribute in-browser binaries and sample code.
- Determinism drift: Floating-point and time sources can vary—lock versions and add tests.
Sources
Read Simon Willison’s write-up: Porting Möbius. Background docs: MDN on WebAssembly and the Emscripten getting started guide.
Key takeaway
Pair Wasm for portability with LLMs for acceleration. You’ll turn niche languages into shareable, in-browser experiences in days—not months.
Get more bite-sized AI build guides—subscribe to our free newsletter: theainuggets.com/newsletter.

