Oxichrome Lets Rust Developers Build Browser Extensions Without JavaScript
Oxichrome hit 100 GitHub stars in 2 days — a Rust framework that compiles browser extensions to WebAssembly with zero hand-written JavaScript and just four macros.

Chrome extension development has long meant accepting JavaScript whether you wanted it or not. Sourav Mishra, whose GitHub handle is 0xsouravm, built Oxichrome to change that: a Rust framework that compiles browser extensions entirely to WebAssembly for both Chrome and Firefox, generating every manifest, JS shim, and HTML file automatically so developers never touch a line of JavaScript by hand.
The project hit 100 GitHub stars within two days of release and landed a mention in the Rust Bytes newsletter. Writing on LinkedIn, Mishra described the motivation plainly: "Chrome extension development is stuck in JavaScript land. The tooling is fragmented, the APIs are clunky, and if you want type safety or performance, you're fighting the ecosystem the entire way."
The entire public API fits in four proc macros: `#[extension]`, `#[background]`, `#[on]`, and `#[popup]`, with `#[options_page]` rounding out the surface. Popup and options pages are marked with `#[oxichrome::popup]` and `#[oxichrome::options_page]`, which flag Leptos components for Oxichrome's build pipeline. Leptos provides fine-grained reactivity with no virtual DOM; the framework describes it as "no JS framework" in the UI layer.
Chrome and Firefox APIs, including `chrome.storage`, `chrome.tabs`, and `chrome.runtime`, are wrapped in typed async Rust interfaces through the `oxichrome-core` crate. The promise is compile-time errors rather than production failures.
Under the hood, Oxichrome is organized into five crates. `oxichrome-macros` expands the attribute macros into `wasm_bindgen` exports. `oxichrome-core` provides the async runtime wrappers. The `oxichrome` facade crate re-exports both and serves as the single dependency a project needs. `oxichrome-build` parses annotated source to discover popup components and event handlers, then generates the glue. `oxichrome-cli` handles scaffolding and builds. The architecture is described in the docs as "Five crates. One command."
Getting started requires installing the `wasm32-unknown-unknown` target and `wasm-bindgen-cli`, then running `cargo install cargo-oxichrome`. From there, `cargo oxichrome new` scaffolds a project with the `oxichrome` crate already wired into `[dependencies]`. A single `cargo oxichrome build` compiles the crate, generates `manifest.json`, JS shims, and HTML, and deposits everything under `dist/chromium/`. Passing ` target firefox` redirects output to `dist/firefox/`, where the generated manifest includes Firefox-specific fields like the gecko ID. Loading for development means pointing Chrome's `chrome://extensions` at `dist/chromium/` with "Load unpacked," or opening `about:debugging` in Firefox for the `dist/firefox/` build.
The generated output structure is explicit: each build produces `manifest.json`, `background.js`, `popup.html`, `popup.js`, `options.html`, `options.js`, and a `wasm/` subdirectory containing `crate_name.js` and `crate_name_bg.wasm`. None of those files require manual editing.
Ajay Kumar covered the framework in a piece dated February 13, 2026, noting that the typical "Rust in the browser" workflow meant compiling to WebAssembly and then spending another day "writing JavaScript glue, fighting callbacks, hand-editing manifest.json, and assembling a folder structure that Chrome will accept." Oxichrome's pitch is that `cargo oxichrome build` handles all of it.
Mishra is positioning this as a ground-up redesign rather than a thin wrapper. "This isn't a wrapper around web-sys with extra steps," he wrote on LinkedIn. "It's a ground-up rethinking of what Chrome extension DX should look like when you're not constrained by JavaScript conventions." Responding to coverage on Medium, Mishra confirmed the roadmap: "I am adding new Chrome APIs in the next version, along with hot reload and a testing framework." The project is MIT licensed.
Know something we missed? Have a correction or additional information?
Submit a Tip

