Run DeepSeek-R1 Locally in the Browser with WebGPU and Zero API Costs
Stop topping up your API account — put the large model in your browser, usable even offline.
Foreword
While you're still adding money to your DeepSeek account, someone has already run the R1 model directly in the browser — no backend needed, no server needed, not even an internet connection needed.
This article takes you from zero to one, packing the distilled version of DeepSeek-R1 into the browser, using WebGPU to accelerate inference, without ever taking out an API Key.
Why do on-device inference?
The three mountains of calling APIs
Calling the DeepSeek / OpenAI API seems convenient, but there are three problems behind it:
| Pain Point | Explanation |
|---|---|
| Expensive | Frequent calls accumulate significant costs, especially for long streaming conversations |
| Insecure | Chat context is sent to a remote server with every request; data privacy cannot be guaranteed |
| Network-dependent | Server downtime or network fluctuations directly crash the user experience |
The idea of on-device models
Since both the problem and the answer are known, why not move the model directly to the user's local machine?
This project explores exactly that path:
Traditional model: Browser ──network──→ DeepSeek Server ──returns answer──→ Browser
This project: Browser's internal GPU runs the model directly → returns answer
No network requests, no waiting in queues, and conversation history stays local forever.
Technical Panorama
Let's look at the key technologies involved in this project, summarized in one sentence:
Use React for the page, TailwindCSS for styling, Transformers.js to orchestrate the model, and WebGPU for inference computation.
React + TypeScript + TailwindCSS: The frontend foundation
// App.tsx core skeleton
function App() {
const [status, setStatus] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
const [loadingMessage, setLoadingMessage] = useState("");
const [progressItems, setProgressItems] = useState([...]);
const IS_WEBGPU_AVAILABLE = !!navigator.gpu;
// ...
}
Why choose React over Vue?
- Large projects in the AI ecosystem mostly use React, with abundant community resources
- Hooks' functional thinking and data-driven view philosophy are particularly suited for handling state transitions during model loading/inference
- TypeScript's type system can intercept a large number of bugs in advance in high-complexity scenarios like model loading
TailwindCSS: No more writing CSS
TailwindCSS's core — utility classes. Writing CSS used to be:
/* Traditional approach: name a class → write a selector → declare properties */
.my-card {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 1rem;
}
Now you just need:
<div className="flex flex-col items-center mb-1 max-w-[400px] text-center">
TailwindCSS provides a bunch of extremely semantic class names; flex is flex, text-center is centered text — what you see is what you get, almost eliminating the need to switch back and forth between hand-written CSS and the editor window. This is particularly useful in AI-driven Vibe Coding scenarios — LLMs are extremely good at this "tell you the class name, you assemble it yourself" pattern.
WebGPU: The GPU in the browser
This is the most hardcore part of the entire project.
Web frontends previously could only use WebGL (a 2011 standard), with limited performance. WebGPU is the new generation browser GPU API, directly comparable to Vulkan/Metal/DX12, allowing the browser to reap the benefits of modern GPUs.
// One line of code to detect if the browser supports WebGPU
const IS_WEBGPU_AVAILABLE = !!navigator.gpu;
// ↑ Returns undefined when not supported
// ↑ Double negation converts to explicit true/false
Currently supported by Chrome/Edge 113+, with Firefox following in Nightly builds.
Transformers.js: Bringing HuggingFace into the browser
This is the official JS library from HuggingFace, allowing you to:
- Load pre-trained models from HuggingFace (including LLMs) in the browser
- Maintain a consistent API with the Python version of Transformers
- Support ONNX format, capable of running directly on WebGPU
// Typical workflow for loading a model with Transformers.js (pseudocode)
const pipeline = await pipeline('text-generation', modelName, {
device: 'webgpu', // Key: specifies running on GPU
});
Once loaded, everything runs completely locally; data never leaves the browser.
Model Selection
This project uses DeepSeek-R1-Distill-Qwen-1.5B-ONNX, with two key pieces of information:
| Attribute | Meaning |
|---|---|
| Distill | Use the original DeepSeek-R1 to teach a small model, allowing it to retain reasoning ability while drastically reducing parameter count |
| 1.5B (1.5 billion parameters) | A fraction of the parameter count of cloud-based large models, but sufficient to complete many reasoning tasks locally |
Small parameter models are not "crippled versions" — on specific tasks, a distilled small model can often achieve 90% of the effect with 1/10th of the compute.
Project Component Hierarchy
App.tsx (Main Component)
├── WebGPU Detection → Prompt user if not supported
├── State Management → null → loading → ready
├── Model Loading Area → Progress bar, file info
├── Chat Area → Input box + inference results
└── Error Handling Area → Friendly prompt when loading fails
The entire application is a single React functional component — before returning JSX is JavaScript logic, after return is the UI. This is the essence of React componentization.
Frontend Direct API Call vs BFF vs On-device Inference
Reviewing three architectural patterns:
① Frontend direct API call (Pure frontend)
Browser ──fetch──→ DeepSeek API
Problem: API Key is exposed in frontend code, visible with a right-click
② BFF pattern (Add an intermediate layer)
Browser ──fetch──→ BFF (Your backend) ──→ DeepSeek API
Problem: An extra backend to maintain, API costs still incurred
③ On-device inference (This project)
Browser's internal GPU runs the model directly
Advantages: Zero cost, zero latency (inference part), data never leaves the browser
Summary
The core value of this project is proving that the browser is not just a "presentation layer"; it is already a complete computing platform.
Tech stack review:
| Layer | Technology | Responsibility |
|---|---|---|
| Interface | React + TypeScript | Componentized UI, state management |
| Styling | TailwindCSS | Atomic CSS, zero hand-written |
| Model Orchestration | Transformers.js | Load / call HuggingFace models |
| Inference Acceleration | WebGPU + ONNX Runtime | In-browser GPU computation |
If you are a frontend engineer, this project can help you understand the full picture of the frontend tech stack in the AI era. If you want to put it on your resume, this project covers React, TypeScript, TailwindCSS, WebGPU, Transformers.js — all the hottest keywords right now.
Project Address: ai_doubao_dcx: Towards AGI, towards Doubao
How to run:
pnpm install && pnpm devBrowser requirement: Chrome/Edge 113+