How I built a Chrome extension that runs Stockfish using WebAssembly
Recently I experimented with running a full chess engine directly inside the browser, without any backend services.
The result is a Chrome extension that runs Stockfish locally using WebAssembly.
This post is a breakdown of how it works, why I built it, and what challenges I ran into.
🚀 Motivation
I wanted to explore a simple question:
How far can we push browser-based computation today?
Specifically:
- Can a chess engine run fully in the browser?
- How viable is WebAssembly for CPU-heavy workloads?
- What limitations does Chrome Extensions (Manifest V3) introduce?
🧠 Architecture overview
The system is built around three main components:
- Stockfish compiled to WebAssembly
- Chrome Extension (Manifest V3)
- Message-based communication between extension contexts
Everything runs locally — there is no backend, no API calls, no server-side logic.
⚙️ How it works
1. WebAssembly Stockfish
The Stockfish engine is compiled into WebAssembly so it can run inside the browser runtime.
This allows near-native performance for heavy computation tasks.
2. Chrome Extension (MV3)
The extension is structured using Manifest V3:
- Background service worker
- Content scripts
- UI popup
One of the main challenges is that service workers are not persistent, which affects how long-running computations must be handled.
3. Communication layer
Because of MV3 constraints, the architecture relies heavily on message passing between:
- UI → background
- background → engine
- engine → UI
Designing this cleanly was more important than raw performance.
⚡ Challenges
1. Extension lifecycle (MV3)
Service workers can be terminated at any time, so you cannot rely on persistent execution.
2. WASM initialization cost
Loading and initializing Stockfish takes noticeable time, so startup optimization matters.
3. Performance vs responsiveness
Running a chess engine can easily block the UI if not handled carefully.
📊 What I learned
- WebAssembly is already production-ready for CPU-heavy tasks
- Architecture matters more than raw computation speed in browser apps
- Chrome Extensions introduce real constraints that affect system design
- Most complexity comes from lifecycle + messaging, not the engine itself
📦 Source code
GitHub:
https://github.com/physicalaff/Knight-Chess-Helper
🧩 Conclusion
This was more of an experiment than a product.
It helped me understand how far modern browsers can go when pushed beyond typical web app workloads.
If you’ve worked with WebAssembly or Chrome Extensions, I’d be curious how you handled similar constraints.
Top comments (0)