extension.js
Extension.js is a zero-config build and dev tool for browser extensions, providing hot module replacement, cross-browser targeting (Chrome, Edge, Firefox), and production packaging via a single CLI. It supports vanilla JS, TypeScript, and frameworks like React, Vue, Svelte, and Preact without webpack or rollup configuration.
MITPermissive — free to use in commercial and proprietary software, with attribution.View license →
Production readiness
4/5- Actively maintainedCommits in the last 6 months
- No known vulnerabilitiesNot yet scanned
- Clear, usable licenseMIT (permissive)
- Proven adoptionWidely used
- Has documentationDocumentation indexed
npm install extension.jsOur analysis
A CLI-driven build toolchain purpose-built for browser extensions that abstracts away Manifest V3 fragmentation and per-browser build pipelines, offering HMR, framework support, and store-ready production bundles.
When to use extension.js
Use it when building Chrome/Edge/Firefox extensions and you want hot reload (including for content scripts), cross-browser builds, and zero bundler configuration. It's especially handy for quickly running GitHub/Chrome samples and for adding modern DX to an existing extension via a single dev dependency.
When not to
If you need Safari support today, deep customization of the underlying bundler, or you already have a tightly tuned webpack/vite extension pipeline, another tool (or rolling your own) may fit better. WXT or Plasmo may be preferable if you want their specific conventions, larger plugin ecosystems, or file-based APIs.
Strengths
- True cross-browser HMR including content scripts, which most competitors require plugin glue for
- Manifest V3 by default with automatic adapters for Chrome, Edge, and Firefox targets
- Framework-agnostic: vanilla, TS, React, Vue, Svelte, Preact, plus WASM examples
- Convenient managed browser binary installation for isolated, clean dev sessions
- Can run any GitHub/Chrome extension sample directly without scaffolding
Trade-offs
- No Safari support yet (listed as upcoming)
- Zero-config approach hides the bundler, limiting deep customization for advanced setups
- Single-maintainer origin and dependence on a small core team is a sustainability consideration
- Competes in a crowded space (Plasmo, WXT, CRXJS) where conventions and ecosystem maturity vary
Maturity
Actively developed with ~5k stars, regular CI, npm distribution, a Discord community, and a documentation/templates site. Manifest V3 and major browser targets are production-supported, though Safari is still pending. Reasonably mature for browser-extension tooling but still evolving.
Extension.js
Build extensions for Chrome, Edge, and Firefox. No build config required.
npx extension@latest create my-extension
cd my-extension
npm run dev
Works with npm, pnpm, yarn, and bun.
Documentation · Templates · Examples · Discord
Why Extension.js
Browser extensions ship with the worst dev experience in modern web. Manifest V3 fragmentation, browser-specific quirks, no hot reload for content scripts, and a separate build pipeline for every target. Extension.js fixes that.
Hot Module Replacement for background, content, popup, and options scripts, including React, Vue, Svelte, and Preact components
Manifest V3 by default, with automatic adapters for Chrome, Edge, and Firefox targets
One CLI for Chrome, Edge, Firefox, and any Chromium or Gecko binary
Zero config, no webpack, no rollup, no plugins to maintain
First-class TypeScript, React, Vue, Svelte, and Preact support
Production builds with
extension build --zip, ready for the Chrome Web Store and Firefox Add-onsDrop-in for existing extensions with one
devDependency
Watch it work
Or skip the install and try a live template in your browser.
How is this different
If you have used Plasmo, WXT, or CRXJS, here is what Extension.js does that the others do not:
CapabilityExtension.jsRun any GitHub sample directlyextension dev https://github.com/.../sampleManaged browser binariesextension install firefox downloads an isolated buildCross-browser HMR for content scriptsBuilt in, no plugin glueProduction zip for the storesextension build --zipFramework agnosticVanilla, TS, React, Vue, Svelte, Preact, no lock-inCustom Chromium and Gecko binaries--chromium-binary, --gecko-binary
Frameworks
ESNextTry outTypeScriptTry outWASMTry outReactTry outVueTry outSvelteTry outPreactTry out
Browsers
Use these flags with extension dev, extension start, or extension preview:
Select a browser:
--browser <chrome | edge | firefox>Custom Chromium binary:
--chromium-binary <path-to-binary>Custom Gecko (Firefox) binary:
--gecko-binary <path-to-binary>
# Chrome (system default)
npx extension@latest dev --browser=chrome
# Edge
npx extension@latest dev --browser=edge
# Custom Chrome/Chromium path
npx extension@latest dev --chromium-binary "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
# Custom Firefox path
npx extension@latest dev --gecko-binary "/Applications/Firefox.app/Contents/MacOS/firefox"
Google Chrome✅ SupportedMicrosoft Edge✅ SupportedMozilla Firefox✅ SupportedApple Safari 🚙 NextChromium-based✅ SupportedGecko-based✅ Supported
Ship to the store
Build a production-ready bundle and zip it for submission to the Chrome Web Store, Edge Add-ons, or Firefox AMO:
# Production build
npx extension@latest build
# Production build packaged as a ZIP
npx extension@latest build --zip
# Per-browser builds
npx extension@latest build --browser=firefox --zip
Useful flags:
--zippackages the build into a ZIP ready for store upload--zip-sourceincludes source files for store source-code review--zip-filename <name>controls the output filename--polyfillenables the cross-browser webextension polyfill
Manage browser binaries
Skip the system-install dance. Extension.js can download and manage isolated browser binaries for clean dev sessions:
# Install a managed Firefox build
npx extension@latest install firefox
# Install Chrome and Edge in one go
npx extension@latest install --browser=all
# Print where managed browsers live
npx extension@latest install --where
Add to an existing extension
Install Extension.js as a dev dependency and wire up your scripts.
npm install extension@latest --save-dev
{
"scripts": {
"build": "extension build",
"dev": "extension dev",
"preview": "extension preview"
}
}
Run npm run dev to develop, npm run build for production, and npm run preview to inspect the production output. See it in action.
Start from a Chrome sample
Pull any sample from Chrome Extension Samples and run it directly:
npx extension@latest dev https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/sample.page-redder --browser=edge
Community
Star the repo if Extension.js helped you ship faster
Join the Discord for help and feedback
Open issues and feature requests on GitHub
Browse production-ready examples
License
MIT (c) Cezar Augusto and the Extension.js authors.