[npm-version-image]: https://img.shields.io/npm/v/extension.svg?color=0971fe
[npm-version-url]: https://www.npmjs.com/package/extension
[npm-downloads-image]: https://img.shields.io/npm/dm/extension.svg?color=0971fe
[npm-downloads-url]: https://www.npmjs.com/package/extension
[action-image]: https://github.com/extension-js/extension.js/actions/workflows/ci.yml/badge.svg?branch=main&color=0971fe
[action-url]: https://github.com/extension-js/extension.js/actions
[discord-image]: https://img.shields.io/discord/1253608412890271755?label=Discord&logo=discord&style=flat&color=0971fe
[discord-url]: https://discord.gg/BRqbPDfPxb
[bestpractices-image]: https://img.shields.io/cii/level/14662?label=Best%20Practices&style=flat&color=0971fe
[bestpractices-url]: https://www.bestpractices.dev/projects/14662
# Extension.js [![Version][npm-version-image]][npm-version-url] [![Downloads][npm-downloads-image]][npm-downloads-url] [![CI][action-image]][action-url] [![Discord][discord-image]][discord-url] [![Best Practices][bestpractices-image]][bestpractices-url]
> The cross-browser extension framework. Build for Chrome, Edge, Firefox, and Safari with no build config required.
```bash
npx extension@latest create my-extension
cd my-extension
npm run dev
```
Works with `npm`, `pnpm`, `yarn`, `bun`, and `deno`.
The CLI itself runs on Node.js 22.12+, Deno 2.5+, and Bun 1.2+.
[Documentation](https://extension.js.org/docs) · [Templates](https://templates.extension.dev/?utm_source=readme&utm_campaign=nav-templates) · [YouTube](https://www.youtube.com/@BrowserExtension) · [Showcase](https://extension.js.org/showcase) · [Blog](https://extension.js.org/blog)
## 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 popup, options, devtools and other extension pages, including React, Vue, Svelte, and Preact components, with targeted reloads for content scripts and the service worker so one save never reloads the whole extension
- **Manifest V3 by default**, with automatic adapters for Chrome, Edge, Firefox, and Safari 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-ons
- **Drop-in** for existing extensions with one `devDependency`
## Watch it work
[](https://extension.js.org/docs)
Or skip the install and try a [live template](https://templates.extension.dev) in your browser.
## How is this different
If you have used [Plasmo](https://www.plasmo.com), [WXT](https://wxt.dev), or [CRXJS](https://crxjs.dev), here is what Extension.js does that the others do not:
| Capability | Extension.js |
| :--------- | :----------- |
| Run any GitHub sample directly | `extension dev https://github.com/.../sample` |
| Managed browser binaries | `extension install firefox` downloads an isolated build |
| Targeted content-script reload across browsers | Built in, only the changed entries re-inject, no plugin glue |
| Production zip for the stores | `extension build --zip` |
| Framework agnostic | [Vanilla](https://templates.extension.dev/javascript), [TS](https://templates.extension.dev/typescript), [React](https://templates.extension.dev/react), [Vue](https://templates.extension.dev/vue), [Svelte](https://templates.extension.dev/svelte), [Preact](https://templates.extension.dev/preact), no lock-in |
| Custom Chromium and Gecko binaries | `--chromium-binary`, `--gecko-binary` |
Extension.js is sponsored by [extension.dev](https://docs.extension.dev/?utm_source=readme), the platform that hosts the build, share and store submission side of shipping an extension. To hand someone an unpublished build behind a link, with no zip and no install on their side, see [Share an unpublished build for review](https://docs.extension.dev/share/unpublished-build-for-review?utm_source=readme).
## Frameworks
## 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:
```bash
# 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:
- `--zip` packages the build into a ZIP ready for store upload
- `--zip-source` includes source files for store source-code review
- `--zip-filename ` controls the output filename, written as `dist/-.zip`
- `--polyfill` enables 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:
```bash
# 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.
```bash
npm install extension@latest --save-dev
```
```json
{
"scripts": {
"build": "extension build",
"dev": "extension dev",
"preview": "extension preview"
}
}
```
Run `npm run dev` to develop, and watch the browser open with your extension already loaded:
[](https://extension.js.org/docs/commands/dev)
Use `npm run build` for production, and `npm run preview` to inspect the production output.
## Start from a Chrome sample
Pull any sample from [Chrome Extension Samples](https://github.com/GoogleChrome/chrome-extensions-samples) and run it directly:
```bash
npx extension@latest dev https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/sample.page-redder --browser=edge
```
[](https://extension.js.org/docs/getting-started/immediately)
## Package managers
Add Extension.js to a project, or run it once without installing, with the package manager you already use.
| Package manager | Add to a project | Run without installing |
| :-- | :-- | :-- |
| npm | `npm install extension@latest --save-dev` | `npx extension@latest create my-extension` |
| pnpm | `pnpm add extension@latest --save-dev` | `pnpm dlx extension@latest create my-extension` |
| Yarn | `yarn add extension@latest --dev` | `yarn dlx extension@latest create my-extension` |
| Bun | `bun add --dev extension@latest` | `bunx extension@latest create my-extension` |
| Deno | `deno add npm:extension@latest` | `deno run -A npm:extension@latest create my-extension` |
Which runtime the CLI then executes on is a separate question, answered below.
## Runtimes
| | Runtime | Status | Notes |
| :-: | :-- | :-- | :-- |
| | Node.js | ✅ 22.12 and newer | The default. `npx`, `pnpm dlx`, `yarn dlx` and `bunx` all land here through the published bin |
| | Deno | ✅ 2.5 and newer | `deno run -A npm:extension@latest`. Deno 2.8.0 is refused because it cannot load `node:querystring`, fixed in 2.8.1 |
| | Bun | ✅ 1.2 and newer | `bunx --bun extension` and `bun run --bun`. Plain `bunx` runs the CLI on Node.js instead, through the published bin |
## Community
- Star the repo if Extension.js helped you ship faster
- Join the [Discord](https://discord.gg/BRqbPDfPxb) for help and feedback
- Open issues and feature requests on [GitHub](https://github.com/extension-js/extension.js/issues)
- Browse production-ready [examples](https://github.com/extension-js/examples)
## Sponsors
Sponsors help the project ship faster releases, better developer experience, and long-term reliability for extension teams.
Documentation is hosted by [Mintlify](https://mintlify.com/?utm_medium=infrastructure&utm_source=extensionjs) through its open source program. Tiers and placement are listed in [BACKERS.md](https://github.com/extension-js/extension.js/blob/main/BACKERS.md).
## Contributing
Bug reports and pull requests are welcome. Read [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) for the dev setup, the test commands, and what a pull request needs to carry.
## License
MIT (c) Cezar Augusto and the Extension.js authors.