If you are starting a browser extension in 2026, you no longer hand-roll a manifest.json, wire up a Webpack config, and pray that hot reload works on content scripts. Three projects now own this space: Plasmo, CRXJS, and WXT.
They look similar from the README, but they make very different bets. One is a full opinionated framework. One is just a build plugin. One tries to be the “Nuxt of extensions.” Pick wrong and you will feel it six months in, usually when you try to ship to Firefox or upgrade a dependency.
This post breaks down all three by the things that actually matter day to day, then gives you a straight decision guide. No “it depends” cop-outs.
TL;DR comparison table
Dimension
WXT
Plasmo
CRXJS
What it is
Full framework
Full framework
Vite plugin
Bundler
Vite
Parcel (custom)
Vite
Frontend frameworks
React, Vue, Svelte, Solid, vanilla
React-first
Any (you wire it)
Cross-browser
Chrome, Firefox, Safari, Edge
Chrome, Firefox, Edge
Chrome / Edge (Chromium)
MV2 + MV3
Both, simultaneously
Both, per build
Pick one
File-based entrypoints
Yes
Yes
No (manual manifest)
Auto-imports
Yes
No
No
Built-in storage / messaging
Yes (+ i18n)
Yes
No
Content-script HMR
Good (UI)
React only
Best (state-preserving)
Publishing / zip
Zip + Firefox source + publish
Zip + publish + Itero TestBed
None
GitHub stars (mid-2026)
~9.5k
~12k
~3.5k
Maintenance
Active
Maintenance mode
Revived (v2.0, Jun 2025)
Best for
Most new projects
React teams, more tutorials
Experts who want control
Sources for these claims are linked at the bottom. Star counts and bundle numbers move, so treat them as a snapshot, not gospel.
The 30-second answer
Starting fresh and want the safe default? Use WXT.
All-in on React and want the biggest pile of existing tutorials? Plasmo still delivers, with caveats.
You are a power user who wants minimal magic and full control of your Vite config? CRXJS.
Now the why.
WXT: the modern default
WXT brings Nuxt-style conventions to extensions. You drop files into an entrypoints/ directory and WXT generates the manifest, registers content scripts, and handles routing for you.
// entrypoints/content.ts
export default defineContentScript({
matches: (‘*://*.github.com/*’),
main() {
console.log(‘Hello from a WXT content script’);
},
});
Enter fullscreen mode
Exit fullscreen mode
Storage is a type-safe, reactive wrapper over browser.storage:
import { storage } from ‘#imports’;
const theme = storage.defineItem’light’ | ‘dark’>(‘local:theme’, {
fallback: ‘dark’,
});
await theme.setValue(‘light’);
Enter fullscreen mode
Exit fullscreen mode
Why people pick it:
Vite under the hood. Near-instant dev server start, fast builds.
Framework-agnostic. React, Vue, Svelte, Solid, or vanilla, all first-class. Want to use Svelte to shave bundle size? Go ahead.
True cross-browser. One codebase builds for Chrome, Firefox, Safari, and Edge, and it papers over the chrome.* vs browser.* namespace mess and MV2/MV3 differences.
Best-in-class dev mode. It opens a browser with the extension already installed and gives you HMR for UI.
Publishing built in. It can produce per-browser zips and even the Firefox source archive reviewers ask for.
Healthy project. Around 9.5k stars and active maintenance as of mid-2026, with production users like Eye Dropper (1M+ users) and ChatGPT Writer (600k+).
Watch-outs: it is the newest of the three, so there are fewer Stack Overflow answers than Plasmo. The conventions are opinionated, which is the point, but you do have to learn them.
Choose WXT if you are starting a new project and want speed, cross-browser support, and a maintained foundation without locking yourself into one UI library.
Plasmo: the React-first framework with the most tutorials
Plasmo was the framework that made extension dev feel like Next.js. Create a popup.tsx, export a React component, done. It still has the largest content library and the slickest first-run experience for React developers.
// content.tsx
import type { PlasmoCSConfig } from “plasmo”
export const config: PlasmoCSConfig = {
matches: (“https://www.github.com/*”)
}
const Overlay = () => div>Injected by Plasmodiv>
export default Overlay
Enter fullscreen mode
Exit fullscreen mode
Storage and messaging ship as dedicated packages:
import { Storage } from “@plasmohq/storage”
const storage = new Storage()
await storage.set(“theme”, “dark”)
Enter fullscreen mode
Exit fullscreen mode
Strengths:
React DX is excellent. Content Script UI with automatic Shadow DOM isolation is genuinely nice.
Biggest learning resource pool. ~12k stars and years of blog posts, videos, and starter repos.
Itero TestBed. A commercial product from the same team for staging and beta distribution before you hit the store, which none of the others offer.
The elephant in the room: maintenance. Multiple sources (including WXT’s own comparison) describe Plasmo as “in maintenance mode with little to no maintainers.” It is still on an older major version of Parcel, and that lag has real consequences, for example it blocks TailwindCSS v4. The high star count is partly legacy momentum, not current velocity. The framework is also still labeled alpha.
Choose Plasmo if you are React-only, you value the depth of existing tutorials and the Itero workflow, and you can accept the risk that feature development has slowed.
CRXJS: not a framework, a superpower for your Vite config
CRXJS (@crxjs/vite-plugin) is the odd one out: it is a Vite plugin, not a framework. You keep full ownership of your vite.config.ts and your project structure. CRXJS just teaches Vite how to build an extension, generate the manifest, and do hot reload.
// vite.config.ts
import { defineConfig } from ‘vite’
import { crx } from ‘@crxjs/vite-plugin’
import manifest from ‘./manifest.json’
export default defineConfig({
plugins: (crx({ manifest })),
})
Enter fullscreen mode
Exit fullscreen mode
Its killer feature is content-script HMR that preserves page state. Edit a content script, see it update on the page without a full reload or losing your place. For UI-heavy content scripts, that feedback loop is the fastest of the three.
The trade-off is that you get no abstractions. No built-in storage wrapper, no messaging helper, no i18n. You bring your own libraries (or raw chrome.* APIs) for everything. Cross-browser is effectively Chromium-only (Chrome and Edge); Firefox support is not the strength here.
CRXJS also has history: it sat in beta for over three years before v2.0 shipped in June 2025. It was recently revived with new maintainers, which is encouraging, but it is the smallest project of the three (~3.5k stars).
Choose CRXJS if you are an experienced developer who wants minimal magic, total control over the build, and the best content-script HMR, and you are happy to assemble the rest of the stack yourself.
Head-to-head on what matters
Build speed and bundle size
WXT and CRXJS both ride Vite (native ESM in dev, esbuild pre-bundling), so dev server start is near-instant. Plasmo’s custom Parcel bundler is the slowest, and developers migrating off it consistently report faster builds afterward. On output size, one benchmark put a WXT build around 400 KB versus roughly 800 KB for the Plasmo equivalent, though a lot of that comes down to your UI library choice (Svelte vs React) rather than the framework alone.
Cross-browser
This is where WXT pulls clearly ahead: one codebase to Chrome, Firefox, Safari, and Edge, with MV2/MV3 handled for you. Plasmo covers Chrome, Firefox, and Edge. CRXJS is realistically Chromium-only. If Firefox or Safari is on your roadmap, that decision is basically made.
Built-in APIs
WXT and Plasmo both give you storage, messaging, and content-script UI out of the box; WXT adds i18n. CRXJS gives you nothing here by design. Less code to maintain vs more control, pick your philosophy.
Maintenance health
For a project you will maintain for years, this is arguably the most important column in the table. WXT is actively developed. CRXJS is freshly revived. Plasmo’s slowdown is the real risk, and a stalled bundler dependency tends to quietly block the modern tools you will want later.
A simple decision tree
Need Firefox or Safari? WXT.
React-only team that lives in tutorials and wants Itero TestBed, and you accept maintenance risk? Plasmo.
Senior dev who wants a bare Vite setup and the fastest content-script HMR? CRXJS.
Anything else, or you just want the boring safe choice? WXT.
Building is only half the job
Here is the part nobody puts in the framework README: the framework decides how fast you build. It does nothing for whether anyone finds and installs your extension.
The Chrome Web Store is a discovery black box. New extensions launch invisible, ranking is heavily influenced by early reviews and keyword placement in your title and description, and you get almost no analytics on where your install funnel leaks (impressions to listing to install to retention).
A few practical things that move the needle once your code is shipped, regardless of which framework you chose:
Get your first real reviews early. Ranking and social proof both stall without them, and fake reviews get your listing pulled.
Make the listing assets convert. Icon, screenshots, and the small promo tile do more for install rate than another feature.
Watch your category. Knowing what competing extensions rank for and what users complain about is cheaper than guessing.
This is the gap ExtensionBooster is built for. It is a growth platform for extension and app developers: a credit-based system for getting real, store-compliant reviews and installs (with rating protection so low-star reviews do not cost you credits), market and competitor analytics to track ratings/users in your category and mine common complaints, and showcase pages that double as SEO backlinks. It also ships free developer tools that are genuinely useful no matter your stack, an icon generator, a screenshot maker, and a promo-tile cropper for the Web Store listing.
Worth bookmarking the free tools before your first submission, since you will need those listing assets the day you ship.
FAQ
Is WXT better than Plasmo?For most new projects in 2026, yes, mainly because it is actively maintained, Vite-fast, and works across all browsers. Plasmo still wins on React-specific tutorial depth and its Itero TestBed.
Is CRXJS a framework?No. It is a Vite plugin that adds Chrome extension support to a Vite project. You keep full control of the config and provide your own storage/messaging/i18n.
Can I migrate from Plasmo to WXT?Yes, and it is a common move. Expect to rewrite entrypoint conventions and swap @plasmohq/storage for WXT’s storage API, but builds and dev startup get noticeably faster.
Which is best for a React extension?Both WXT and Plasmo handle React well. Plasmo is React-first with more examples; WXT gives you React plus a maintained, cross-browser foundation and the option to use a lighter UI library later.
Which has the best hot reload?CRXJS for content scripts (state-preserving). WXT for overall UI dev experience. Plasmo’s HMR is tuned for React and falls back to full reloads otherwise.
Bottom line
WXT is the default I would hand a new team in 2026.
Plasmo is still a strong React experience if you accept the maintenance risk and want the Itero workflow.
CRXJS is the connoisseur’s choice for control and content-script HMR.
Pick the build tool that fits your team, then put real energy into the part that frameworks ignore: getting discovered and installed.
Sources: WXT official comparison, WXT homepage, Plasmo docs, The 2025 State of Browser Extension Frameworks, and project GitHub repos.


