Documentation Index
Fetch the complete documentation index at: https://extension.js.org/llms.txt
Use this file to discover all available pages before exploring further.


The cross-browser extension framework
Build browser extensions across all major browsers with one modern workflow. Extension.js handles manifest compilation, browser-specific output, and packaging.
npx extension@latest create my-extensionOne manifest.json.
All browsers.
Browser-prefixed keys (chrome:, firefox:,
edge:) filter at compile time. Unprefixed keys apply
everywhere.
âmanifest_versionâ:3,ânameâ:âMy Extensionâ,âversionâ:â1.0.0â,âactionâ: âdefault_popupâ:âpopup.htmlâ,âchrome:backgroundâ: âservice_workerâ:âsw.tsâ,âfirefox:backgroundâ: âscriptsâ:[âsw.tsâ]
Why use a browser extension framework?
Browser extensions need different files, browser APIs, manifest formats, permissions, and build outputs than regular web apps. A browser extension framework removes that glue: one workflow handles Chrome, Edge, and Firefox extension development, manifest filtering per target, reload behavior tuned for service workers and content scripts, and packaging ready for the Chrome Web Store, addons.mozilla.org, and the Edge Add-ons store.
Extension.js gives you that workflow. One JavaScript or TypeScript
project, onemanifest.json, separatedist/<browser>outputs, and a CLI that gets out of your way, making it effortless to
ship a single codebase as a cross-browser extension.
Watch the full developer workflow
From scaffold to running extension, in one modern toolchain.
Core features for the full extension lifecycle
Build, test, and ship for every browser with one modern extension workflow.
Compile one extension into browser-specific output
Build once for Chrome, Edge, Firefox, and custom Chromium or Gecko targets. Browser-specific output stays predictable across development, testing, and release builds.
Keep extension structure explicit
Manifest, paths, and emitted assets stay in sync as your extension grows.

Tune behavior with config
Override defaults through extension.config.js for
custom builds.
Bring your preferred stack
Start with React, Vue, Svelte, TypeScript, or JavaScript. Keep one workflow so your team picks the right UI model without changing the extension toolchain.
Inject environment values cleanly
Load environment values by browser and mode, then replace them across JavaScript, JSON, and HTML. Development secrets never leak into production bundles.



Build, preview, package
One flow from local check to store-ready artifacts per browser.
Choose your framework. Keep your workflow.
Start with production-ready templates for React, Preact, Vue, Svelte, TypeScript, or JavaScript.
React
Component-based UI with full Manifest V3 (MV3) compatibility. Ready-to-ship popup, options, and content scripts.
Preact
Same React API in a 3kB runtime. Great for content scripts where bundle size matters.
Vue
Progressive framework with single-file components, wired up for extension contexts out of the box.
Svelte
Compile-time UI with smaller runtime. Ideal when every kilobyte in a content script counts.
TypeScript
Static types for popup, content, and background scripts. Catch manifest and messaging bugs at compile time.
JavaScript
Plain ES modules, no compile step required. Start fast and add tooling when you need it.
Coming from another framework?
Most React, Vue, and Svelte source files copy across without rewriting. The work is replacing the bundler config and moving generated manifests back to a real manifest.json.
Backing the open-source core
Sponsors help the project ship faster releases, better developer experience (DX), and long-term reliability for extension teams.
Frequently asked questions
What is a browser extension?
What is a browser extension?
Is Extension.js a Chrome extension framework?
Is Extension.js a Chrome extension framework?
--browser=chrome, --browser=firefox, or
--browser=edge. See Browsers
available.How does Extension.js handle hot module replacement during development?
How does Extension.js handle hot module replacement during development?
npx extension dev and the CLI watches your project for changes.
Edits to popups, content scripts, service workers, and options pages
trigger the fastest safe update path. The CLI uses hot module
replacement (HMR) when supported and targeted reloads otherwise. It
automatically resolves common pain points like stale service workers and
missed content-script updates.How do I build one extension for Chrome, Edge, and Firefox?
How do I build one extension for Chrome, Edge, and Firefox?
Can I use React, Preact, Vue, Svelte, or TypeScript?
Can I use React, Preact, Vue, Svelte, or TypeScript?
Does Extension.js support Manifest V3?
Does Extension.js support Manifest V3?
How do I troubleshoot Manifest V3 service worker and permissions issues?
How do I troubleshoot Manifest V3 service worker and permissions issues?
type: "module", the new
web_accessible_resources shape, the split between permissions and
host_permissions, and declarative_net_request differences in
Firefox. See Manifest V3 troubleshooting
for the fixes.How do I migrate from a custom webpack or Vite setup?
How do I migrate from a custom webpack or Vite setup?
Does Extension.js work with monorepos and environment variables?
Does Extension.js work with monorepos and environment variables?
Is Extension.js free to use?
Is Extension.js free to use?
Does Extension.js support Safari?
Does Extension.js support Safari?
--browser=safari is not a CLI target today. You can still
author Safari extensions with shared web code and add Safari-specific
build steps outside this workflow. See Browsers
available
for the current scope.What does Extension.js add to my bundle?
What does Extension.js add to my bundle?
extension build) emit only the code your
extension references plus a small reload runtime that is removed in
production. Dev builds include extra HMR and reload glue. Output sits
under dist/<browser> so you can compare sizes between browsers.
Content-script bundles stay close to what your source plus your
chosen UI framework would produce.How do I migrate from CRXJS, WXT, or Plasmo?
How do I migrate from CRXJS, WXT, or Plasmo?
manifest.json
with browser-prefixed
keys, and updating
package.json scripts. See Migrate from
CRXJS for the step-by-step.

