I spent three weeks debugging a memory leak that only appeared when the user’s internet connection dropped for more than two seconds. It wasn’t a server timeout. It wasn’t a cache miss. It was the moment I realized that for a real-time, text-based adventure, the round-trip to a cloud API was the bottleneck—not just for latency, but for privacy and reliability.
That frustration led to MysteryMist. It’s a detective game where your typing speed uncues clues, but the core engineering challenge wasn’t the game logic. It was convincing a private on-device AI to run a full narrative engine in the browser, offline, with zero data leaving the device.
The WebGPU Wedge
The premise is simple: you are a detective in a foggy, noir-inspired city. You don’t click to progress; you type. The faster you type, the clearer the vision becomes. Clues appear dynamically based on your input rhythm. But here is the twist: the "DM" (Dungeon Master) is a small model that runs in your browser.
Most web games treat AI as a luxury feature—something you pay for via subscription, which requires a constant network connection. If the server is down, the game is dead. If the network is slow, the immersion breaks.
I wanted to solve the "offline AI" problem without forcing users to install a 2GB desktop app or run a local LLM server with 16GB of RAM. The solution was WebGPU. By leveraging the GPU directly through the browser, we can run inference on a private on-device AI that never touches the cloud.
This means the game works on an airplane. It works when your Wi-Fi goes down. And critically, your conversation with the AI is never uploaded. There is no telemetry, no training data collection, and no privacy policy to read because there is no data to collect.
Engineering the Constraint
Building this required a shift in how we think about model size. We aren’t using the massive 70B+ parameter models that dominate headlines. We are using a highly quantized, small model that runs in your browser. This isn’t a compromise; it’s a design choice.
The constraint of running entirely on the client side forced us to optimize the prompt structure. We can’t send a 50,000-token context window back and forth over an API. Instead, the game state is compressed into a dense, structured JSON blob that the on-device AI processes in real-time.
Here is a simplified view of how the inference loop works in the main thread:
// The core inference loop runs on the main thread,
// blocking only for the duration of the generation.
// No web workers, no async/await overhead for network I/O.
const result = await onDeviceAI.generate({
prompt: currentSceneContext,
maxTokens: 64,
temperature: 0.7
});
// The result is immediately rendered to the DOM.
// Latency is determined solely by the user's CPU/GPU power,
// not by network jitter.
This approach has trade-offs. The model is smaller, so it doesn’t have the vast world knowledge of a cloud-based giant. It relies heavily on the structured context we feed it. But the trade-off is worth it: the latency is sub-100ms on modern devices, and the experience is seamless. There is no "waiting for the cloud" spinner. You type, and the world reacts.
The Honest Pricing Model
MysteryMist is a paid tool. It’s not a free-to-play mobile game with ads. The development is supported by a one-time purchase or subscription, which includes a 7-day trial. However, because the core engine is the same, the games themselves have free turns. You can play the introductory cases without paying, giving you a chance to experience the typing mechanics and the on-device AI flow before committing.
This model reflects the cost of running the service for updates and new cases, but the heavy lifting—the actual AI inference—happens on your hardware. You aren’t paying for compute; you’re paying for the curation, the puzzle design, and the engine.
Why This Matters for Developers
If you are building web applications, consider what parts of your stack truly need to be online. We have become accustomed to sending everything to the cloud because it was easier. But with WebGPU and WebAssembly, the browser is becoming a powerful compute environment.
By moving inference to the client, you gain privacy, reduce server costs, and improve resilience. The user’s device is a powerful computer. We just haven’t always used it as one.
I’m curious to hear from others in the community: Have you experimented with on-device AI in your own projects? What were the biggest hurdles you faced in getting models to run efficiently in the browser without sacrificing performance?
Top comments (0)