DEV Community

techpanda
techpanda

Posted on

Building a Browser-Based AI Feature With No Backend

Oct 27, 2026
For a long time, adding AI to a web app meant one thing: sending user data to a server, waiting for a hosted model to answer, and paying for every request. That is no longer the only option. Modern browsers can run compact machine learning models directly on a visitor's device, using WebAssembly and WebGPU, with no inference server involved at all.
This guide explains how that works, when it makes sense, and how to build a small feature the practical way. It's written for developers who are comfortable with JavaScript but new to running models in the browser.
Why Run Models in the Browser?
Before choosing the approach, it helps to understand what you gain and what you give up.
What you gain:
Privacy. Text, images, and audio never leave the device, which simplifies data protection concerns and builds user trust.
Cost. Inference runs on the visitor's hardware, so you don't pay per request or per token. Your bill is mostly static file hosting.
Latency. There's no network round trip once the model is loaded, so responses
 can feel instant for small tasks.
Offline use. After the first download, features can keep working without a connection.
Simple deployment. There's no GPU server to provision, scale, or monitor.
What you give up:
Model size. Browsers can't comfortably run the largest models. You're limited to small, optimized ones.
First-load weight. Models are downloaded files, often tens or hundreds of megabytes.
Uneven hardware. A recent laptop with a good GPU and an older phone behave very differently.
Less control. You can't easily update or inspect a model after it's running on someone else's device.
In short, browser-based AI shines for focused, narrow tasks, not for general-purpose assistants that need frontier-level reasoning.
How It Works: WebAssembly and WebGPU
Two browser technologies make this possible, and they play different roles.
WebAssembly (WASM)
WebAssembly is a compact binary format that lets code written in languages such as C++ or Rust run in the browser at near-native speed on the CPU. Machine learning runtimes compile their core engines to WASM, so they can execute model operations without needing special hardware. WASM works almost everywhere, which makes it the dependable baseline.
Two details matter in practice. First, SIMD (single instruction, multiple data) support speeds up the math-heavy parts considerably. Second, multithreaded WASM relies on SharedArrayBuffer, which browsers only enable on pages that are cross-origin isolated. That means your server must send the right headers, typically Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp. Without them, you'll often fall back to a single thread and see slower results.
WebGPU
WebGPU is the modern browser API for accessing the graphics card. Unlike older approaches, it supports general-purpose compute, which is exactly what neural networks need: huge numbers of parallel calculations. Running a model on the GPU can be several times faster than on the CPU, and it makes larger models practical.
Support has expanded across major browsers in recent years, but it still varies by version, operating system, and hardware. Treat WebGPU as an upgrade you detect at runtime, never as something you can assume.
Choosing Your Tools
You rarely need to talk to these APIs directly. Several libraries wrap them for you:
Library
Best for
Notes
Transformers.js
Common tasks like classification, summarization, embeddings, speech
Simple pipeline API; runs on ONNX Runtime Web
ONNX Runtime Web
Custom or converted ONNX models
Offers both WASM and WebGPU backends
WebLLM
Running small chat-style language models
Focused on WebGPU; handles model caching
MediaPipe tasks
Vision, audio, and small language model tasks
Google-maintained task libraries
TensorFlow.js
Existing TensorFlow models
Supports WebGL, WASM, and WebGPU backends

For most developers starting out, Transformers.js offers the gentlest learning curve because a few lines of code give you a working model.
Building a Small Example
Let's build a simple feature: classifying the sentiment of a user's text entirely in the browser. The pattern applies to many other tasks.
Step 1: Detect What the Device Can Do
Check for WebGPU first, and fall back to WASM when it isn't available:
async function pickDevice() {
if ('gpu' in navigator) {
try {
const adapter = await navigator.gpu.requestAdapter();
if (adapter) return 'webgpu';
} catch (err) {
console.warn('WebGPU check failed', err);
}
}
return 'wasm';
}
Step 2: Load the Model
With Transformers.js, loading a model is a single call. The library downloads the files once and caches them for later visits:
import { pipeline } from '@huggingface/transformers';

const device = await pickDevice();

const classify = await pipeline(
'sentiment-analysis',
'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
{ device }
);
Step 3: Run Inference
const result = await classify('The new update is fantastic.');
console.log(result);
// [{ label: 'POSITIVE', score: 0.99 }]
That's the whole core of the feature. Everything else is about making it feel good to use.
Step 4: Keep the Interface Responsive
Inference is heavy, and running it on the main thread can freeze your page. Move it into a Web Worker and talk to it with messages:
// worker.js
import { pipeline } from '@huggingface/transformers';

let classifier = null;

self.onmessage = async (event) => {
const { type, text, device } = event.data;

if (type === 'load') {
classifier = await pipeline(
'sentiment-analysis',
'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
{ device }
);
self.postMessage({ type: 'ready' });
}

if (type === 'run' && classifier) {
const output = await classifier(text);
self.postMessage({ type: 'result', output });
}
};
// main.js
const worker = new Worker(new URL('./worker.js', import.meta.url), { type: 'module' });

worker.postMessage({ type: 'load', device: await pickDevice() });

worker.onmessage = ({ data }) => {
if (data.type === 'ready') enableInput();
if (data.type === 'result') showSentiment(data.output[0]);
};
This keeps scrolling, typing, and animations smooth while the model works in the background.
Designing for the Real World
The code above is the easy part. A production-quality feature needs a few extra considerations.
Handle the Download Gracefully
Users will wait for a 5 MB file but not for a silent 500 MB download. Show a progress bar, explain what's happening, and ideally let the user opt in before a large download begins. Most libraries expose progress callbacks you can connect to your interface.
Choose Small, Quantized Models
Quantization stores model weights with fewer bits, such as 8-bit or 4-bit integers instead of 32-bit floats. This can cut file size and memory use dramatically with a modest loss in accuracy. For browser use, a quantized model is usually the right default. Always test accuracy on examples from your own use case rather than trusting general benchmarks.
Cache Intelligently
Models are cached using browser storage such as the Cache API or the Origin Private File System. Browsers can evict stored data when space runs low, so check availability with navigator.storage.estimate() and consider requesting persistent storage using navigator.storage.persist() for important models.
Watch Memory and Battery
Large models can exhaust memory on phones and cause tabs to reload. Load models only when the feature is actually needed, unload them when finished, and avoid running continuous inference in the background. GPU-heavy work also drains batteries, so consider restricting the largest models to desktop-class devices.
Always Provide a Fallback
Some devices won't run your model at all. Decide in advance what happens then. Options include a lighter model, a simpler rule-based approach, or an optional server-based path for users who consent to it. A feature that degrades gracefully is far better than one that silently breaks.
Be Honest About Limits
Small models make mistakes. Label AI output clearly, give users an easy way to correct it, and avoid using on-device models for high-stakes decisions without human review.
Good Use Cases
Browser-based AI works best for tasks that are narrow, private, or latency-sensitive:
Classifying or tagging user-written text
Generating semantic search embeddings for local content
Transcribing short audio clips
Detecting objects or removing backgrounds in images
Offering writing suggestions in an editor
Redacting sensitive details before anything is uploaded
For long, complex reasoning tasks or very large models, a server-based approach is still the better fit. Many teams combine both: small local models for quick, private tasks and a hosted model for the hard cases.
Final Thoughts
Running AI in the browser has moved from clever demo to a legitimate engineering choice. With WebAssembly as the dependable foundation and WebGPU as a performance boost where available, you can ship features that are private, fast, and cheap to operate.
Start with one narrow task, pick a small quantized model, run it in a worker, and detect device capabilities at runtime. Once that foundation works, scaling up to richer features is mostly a matter of choosing better models and polishing the experience. The server can stay out of the loop, and your users' data stays where it belongs.
For more blog visit our site TechPanda

Top comments (0)