WXT: a Vite-based framework for building browser extensions
⚡ Next-gen Web Extension Framework
At a glance
- What is it?
- WXT wraps Vite and the WebExtension manifest into a file-based project layout with hot reload, auto-imports and a module system. It is aimed at teams shipping one extension to Chrome, Firefox and Edge, and its trade-offs sit in the build conventions it imposes.
- Who is it for?
- Adopt WXT if you are starting a new extension in TypeScript and want Vite's dev server, file-based entrypoints and one build that targets Chrome, Firefox and Edge. Do not adopt it if your extension is a small vanilla JavaScript package that you rebuild rarely, or if you depend on a bundler plugin that has no Vite equivalent, because the framework's value is concentrated in the dev loop and the manifest generation you would then be replacing.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem WXT solves for extension authors
Building a browser extension means maintaining more than application code. You keep a manifest.json in sync with the files on disk, wire up separate entrypoints for the background service worker, content scripts and popup, and rebuild by hand or with a bundler config that has nothing to do with extensions. WXT targets that gap. The README describes it as a "Next-gen framework for developing web extensions" and quotes the framing "It's like Nuxt, but for Web Extensions", which is the clearest statement of intent in the repository: take the conventions a meta-framework applies to a web app and apply them to an extension.
The audience is TypeScript developers who already use a bundler. The README lists TypeScript, auto-imports and frontend framework agnosticism among the features, and says the framework "works with Vue, React, Svelte, etc". If you write a content script in plain JavaScript and load it unpacked from a folder, WXT adds a build step and a project structure you do not currently need. If you maintain several entrypoints, target more than one browser, or want the dev server to reload the extension when a file changes, the conventions start paying for themselves.
File-based entrypoints and what the build produces
The mechanism visible in the repository is conventional over configuration. The README lists "File based entrypoints" as a feature, meaning the build derives the extension's entrypoints from files in the project rather than from a hand-written manifest. The manifest is generated output, not a file you edit, which is the main structural difference from a plain Vite setup with a static manifest.json copied into the bundle.
The build itself runs on Vite. The workspace catalog in the root package.json pins vite at ^8.2.0, and the repository's own tooling includes tsdown and oxlint. The dev loop is the feature the README leads with: "Dev mode with HMR & fast reload". HMR applies to extension pages such as the popup or an options UI, while the reload path handles the parts of an extension that a browser cannot hot-swap, such as the background worker or a content script. That split is inherent to the platform, not a WXT limitation, and the README does not describe how each is triggered.
The project also ships a module system for sharing code between extensions, and the release list shows that system is used in practice: @wxt-dev/runner and @wxt-dev/auto-icons are published as separate packages, with runner-v0.1.3 and auto-icons-v1.1.2 released on 2026-08-11 and 2026-08-02 respectively. A module is the unit of reuse here, so a pattern you want across three extensions becomes a dependency rather than a copied directory.
Installing WXT and bootstrapping a first extension
The README's Quick Start gives three equivalent bootstrap commands, one per package manager. The npm form is the one most readers will use:
npx wxt@latest initThe README also shows pnpm dlx wxt@latest init and bunx wxt@latest init for the other two package managers. The command scaffolds a new project, and the README points to the installation guide at wxt.dev/guide/installation.html for anything beyond the scaffold. What you get is a directory with the framework as a dependency and the entrypoint layout the build expects.
Once the project exists, the dev server is the daily command. The README does not print the script names in the excerpt above, so check the package.json the scaffold writes before assuming a name; the framework's own scripts in the repository are not the ones your project will have. The dev command starts Vite and loads the extension into a browser with the reload behaviour described in the README's feature list.
For a production build, the framework needs to know which browser you are targeting, since the same source has to produce an MV2 or MV3 manifest depending on the target. The README states "Supports all browsers" and "Supports both MV2 and MV3" but does not show the target flag in the excerpt, so read the configuration page at wxt.dev/api/config.html for the exact key. The repository also advertises "Bundle analysis" as a feature, which is the tool to reach for when a content script grows past what you expected.
Where WXT constrains you
The cost of file-based entrypoints is that the build owns the manifest. If your extension needs a manifest key the framework does not expose, or a permission that has to be computed at build time, you are working against the framework rather than with it. The README does not document an escape hatch for a fully hand-written manifest, and it does not document rollback, so a project that outgrows the conventions faces a migration rather than a config change.
The frontend framework agnosticism is real but shallow. WXT integrates with Vue, React and Svelte at the build level; it does not give you their routing, data fetching or component conventions, and it does not need to. If you were hoping the Nuxt comparison extends to server routes or a rendering model, it does not, because an extension has no server.
The dev loop is also the part most likely to mislead. HMR in an extension page is not the same guarantee as HMR in a web app, because the background worker and content scripts live under browser lifecycle rules the dev server cannot override. Expect a full reload for those, and treat the reload speed as the number that matters, not the HMR badge.
Finally, the repository's own engine constraint is bun >=1.3.5 in the root package.json. That governs contributing to WXT, not using it, but it signals that the maintainers' toolchain assumes a recent runtime and is not built around npm-first workflows.
WXT compared with Plasmo
Plasmo is the comparison people search for, and the two projects share a premise: a framework that generates the extension manifest from your source layout and gives you a dev server. The difference is the underlying bundler and the surrounding conventions. WXT is built on Vite, which is visible in the repository's dependency pins and in the framework's configuration surface. Plasmo's approach centers on its own build pipeline and a component-oriented API for extension UI.
That difference matters most when you already have Vite plugins you rely on, or when your team knows Vite's config model. With WXT those carry over; with a framework that owns its pipeline, you adapt. It matters less if your extension is a popup and a content script with no unusual build requirements, where either framework removes the same manual manifest work.
The README's framing of WXT as "like Nuxt, but for Web Extensions" is the honest summary of its design philosophy: conventions first, with the bundler underneath exposed when you need it. If you want a framework that hides the bundler entirely, that is a different product decision, and it is worth reading both projects' configuration docs before choosing.
Licence and the cost of keeping up
WXT is MIT-licensed, per the LICENSE file and the badge in the README. MIT permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is a permissive baseline, but it says nothing about the licences of the framework's dependencies or of any WXT module you add; audit those separately, since a module is a normal package with its own terms. Nothing here is legal advice.
On maintenance, the repository is not archived and the last push was on 2026-09-18, three days before this writing. Releases are frequent and versioned per package: wxt v0.21.4 on 2026-08-11, @wxt-dev/runner v0.1.3 the same day, @wxt-dev/auto-icons v1.1.2 on 2026-08-02. The wxt package is still on a 0.x line, which is the practical upgrade consideration: minor versions in 0.x semver may carry breaking changes, so pin the version in your package.json and read the changelog linked from the README before bumping. The repository keeps a CHANGELOG.md under packages/wxt, which is where those notes live.
Upgrade cost also depends on how much of the framework you use. A project that only uses the entrypoint conventions is cheap to move forward; one that depends on several WXT modules pays for each module's release cadence in addition to the core's.
Editorial conclusion
Adopt WXT if you are starting a new extension in TypeScript and want Vite's dev server, file-based entrypoints and one build that targets Chrome, Firefox and Edge. Do not adopt it if your extension is a small vanilla JavaScript package that you rebuild rarely, or if you depend on a bundler plugin that has no Vite equivalent, because the framework's value is concentrated in the dev loop and the manifest generation you would then be replacing. Before committing, run npx wxt@latest init, build the generated project for both a Chrome MV3 target and a Firefox target, and confirm the manifest your extension actually needs is produced; the README does not document rollback or migration away from the framework.
Frequently asked questions
What does WXT stand for?
The README and repository files do not expand the name, so there is no documented meaning to report. Treat WXT as the project's name rather than an acronym with a published definition.
What are the benefits of WXT?
The README lists support for all browsers and both MV2 and MV3, a dev mode with HMR and fast reload, file-based entrypoints, TypeScript, auto-imports, automated publishing, frontend framework agnosticism, a module system for sharing code between extensions, quick bootstrapping and bundle analysis.
How do I install WXT?
The README's Quick Start bootstraps a new project with npx wxt@latest init, or pnpm dlx wxt@latest init, or bunx wxt@latest init. The installation guide at wxt.dev/guide/installation.html covers the rest.
What is the history of WXT?
The repository does not include a documented project history. The README credits @aklinker1 and the community, and the release list shows the current line at wxt v0.21.4, released on 2026-08-11.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wxt-dev-wxt)