dev-tools 6 min read

Extension.js – Build Browser Extensions Without Build Config

A CLI framework that handles Chrome, Edge, and Firefox browser extension development with zero config, built-in HMR, and Manifest V3 support. Quick setup.

By
Share: X in
Extension.js – cross-browser extension framework

TL;DR

TL;DR: Extension.js is a zero-config CLI for building Chrome, Edge, and Firefox extensions. One command scaffolds a project, one command runs it in all targets, and production builds are ready for the web store.

Source and Accuracy Notes

All claims verified from source. See links below.

The Problem: Browser Extensions Have the Worst Dev Experience

Building a cross-browser extension in 2026 means juggling Manifest V3 differences between Chrome, Edge, and Firefox, managing separate build pipelines, and losing hot reload the moment you touch content scripts. Existing frameworks like Plasmo, WXT, and CRXJS help, but each brings its own trade-offs around configuration complexity and feature scope.

What Is Extension.js?

Extension.js is a cross-browser extension CLI that puts zero-config first. You run one command, pick from live templates, and your project is ready to develop and build — no webpack, no rollup, no plugins to maintain. It targets Chrome, Edge, and Firefox from a single codebase.

The README pitches it as the framework that “fixes” the browser extension dev experience. Key features:

  • Hot Module Replacement for background, content, popup, and options scripts, including React, Vue, Svelte, and Preact
  • Manifest V3 by default with automatic adapters for all three browsers
  • One CLI for Chrome, Edge, Firefox, and any Chromium or Gecko binary
  • Zero config — no webpack, no rollup, no plugins
  • First-class TypeScript, React, Vue, Svelte, and Preact support
  • Production builds with extension build --zip, ready for the Chrome Web Store and Firefox Add-ons
  • Drop-in for existing extensions by adding it as a devDependency

Setup Workflow

Step 1: Create a new extension

npx extension@latest create my-extension

You’ll see a list of live templates you can run directly in the browser, including Vanilla JS, TypeScript, React, Vue, Svelte, and Preact.

Step 2: Run in development mode

cd my-extension
npm run dev

The CLI opens your extension in the target browser with HMR active. By default it uses your system Chrome, but you can override with a flag:

npm run dev -- --browser firefox

For managed browser binaries (useful in CI or if you don’t have Firefox installed locally):

npx extension install firefox

Then reference it with:

npm run dev -- --browser firefox --gecko-binary ~/.extension-dev/firefox/firefox-bin

Step 3: Build for production

npm run build

This outputs a /dist-zip folder with .zip files ready to upload to the Chrome Web Store or Firefox Add-ons.

Step 4: Try without installing

If you want to kick the tires before committing to a project install, Extension.js lets you run any GitHub sample directly:

npx extension dev https://github.com/extension-js/examples --template react

How It Differs from Existing Tools

The README makes a direct comparison with Plasmo, WXT, and CRXJS:

| Capability | Extension.js | | :--------- | :----------- | | Run any GitHub sample directly | extension dev https://github.com/.../sample | | Managed browser binaries | extension install firefox | | Cross-browser HMR for content scripts | Built in | | Production zip for stores | extension build --zip | | Framework agnostic | Vanilla, TS, React, Vue, Svelte, Preact |

Deeper Analysis

Manifest V3 and background scripts

Extension.js defaults to Manifest V3, which means service workers instead of persistent background pages. The CLI handles the manifest generation and ensures the background script lifecycle works correctly across Chrome’s stricter MV3 enforcement and Firefox’s more permissive approach.

Content script HMR

The killer feature for active development is that content script changes hot-reload without restarting the extension or reloading the tab. This is notoriously hard to get right in content scripts (as opposed to popup/options pages) and typically requires plugin glue with webpack or rollup. Extension.js bakes this in.

Framework choice

Unlike Plasmo (which is React-first) or WXT (which is TypeScript-first), Extension.js treats framework support as a first-class citizen with equal treatment across all six options. The templates at templates.extension.dev make this easy to preview before installing.

Practical Evaluation Checklist

  • Create a new extension with one command
  • Run npm run dev — verify HMR fires on popup and content script edits
  • Switch browser with --browser firefox
  • Run npm run build — verify .zip output in /dist-zip
  • Add the package as a devDependency to an existing extension project — verify it doesn’t clobber an existing manifest.json

Security Notes

Extension.js is a build tool, not a runtime dependency. It runs in your local development environment and produces static extension bundles. The security posture of the built extension depends entirely on your code and the permissions you request in the manifest. Review the generated manifest.json before publishing to any store.

FAQ

Q: Does it support Manifest V2 extensions? A: The project defaults to Manifest V3. MV2 support depends on browser vendor policies — Chrome has deprecated MV2, Firefox still supports it but the ecosystem is shifting. Check the Extension.js docs for MV2-specific configuration if you need it.

Q: Can I use this with an existing Chrome Extension? A: Yes. Add extension as a devDependency, move your source to src/ if needed, and configure extension.config.js for any custom paths. The README calls this a “drop-in” experience.

Q: Does it work with bun or pnpm? A: Yes. The README explicitly states it works with npm, pnpm, yarn, and bun.

Q: How does it handle browser-specific APIs? A: Extension.js generates per-browser manifests and provides adapters for common API differences. For deep browser API differences, you’ll still need conditional code — the CLI doesn’t abstract away all browser runtime differences.

Conclusion

Extension.js solves the cross-browser extension dev experience by treating zero-config as a first-class constraint, not an afterthought. If you’ve been managing separate build pipelines for Chrome and Firefox, or losing hours to content script HMR调试, this CLI is worth a try. The npx extension@latest create flow gets you from zero to a running extension in under a minute.

For a full comparison against WXT and Plasmo, the Extension.js docs have a capability matrix and links to try each template live in the browser.