Browser extensions are back. Here's how to ship a Manifest V3 + WXT extension that actually sells.
Extensions used to be a niche side project. Now they're a real distribution channel for AI-powered tools. I shipped one last month — here's the path I'd take if I were starting today.
Browser extensions are having a moment again. AI-powered tools (writing assistants, summarizers, scrapers, schedulers) are the new must-have. WXT is the framework I'd use today — it's like Vite for extensions, supports MV3, hot-reload, and Chrome + Firefox in one codebase. Here's the recipe.
Why now?
Three things made extensions interesting again:
- AI changed what an extension can do. A tab-summarizer used to require a backend, an API, and a queue. Now it's a fetch to OpenRouter or Anthropic and a popup. Distribution is suddenly bigger than implementation.
- Manifest V3 finally settled down. The migration was painful but it's done. Service workers replaced background pages and most flake is fixed.
- The Chrome Web Store still has insane reach. A small but well-designed extension can hit 10k installs in a month if it lands on Product Hunt or X.
The stack I'd use today
- WXT — Vite-based, MV3-first, hot-reload that actually works
- React or Svelte for the popup and side-panel UIs
- Cloudflare Workers for the backend (auth, billing, AI gateway)
- chrome.storage.local for per-user state (encrypted)
- Stripe for billing (Checkout link from the popup)
That's it. No Docker, no backend server to baby-sit, no separate auth provider needed.
Step 1 — Scaffold
npx wxt@latest init my-extension
cd my-extension
npm install
npm run dev # opens Chrome with hot-reload
WXT auto-detects content scripts, service workers, popups, options pages — you just drop files in entrypoints/ and they show up.
Step 2 — A useful extension in 50 lines
Let's build a "summarize this page" tool. Click the icon, get a summary in a popup.
entrypoints/popup/App.tsx:
import { useState } from 'react'
export default function App() {
const [summary, setSummary] = useState('')
const [loading, setLoading] = useState(false)
async function summarize() {
setLoading(true)
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true })
const [{ result }] = await chrome.scripting.executeScript({
target: { tabId: tab.id! },
func: () => document.body.innerText,
})
const r = await fetch('https://my-api.workers.dev/summarize', {
method: 'POST',
body: JSON.stringify({ text: result.slice(0, 8000) }),
})
setSummary(await r.text())
setLoading(false)
}
return (
<div style={{ padding: 16, width: 320 }}>
<button onClick={summarize} disabled={loading}>
{loading ? 'Summarizing…' : 'Summarize page'}
</button>
<p>{summary}</p>
</div>
)
}
The Worker on the other end just calls Anthropic / OpenAI and streams back a summary. ~30 lines.
Step 3 — The parts the docs skip
The docs are good at scaffolding. They are bad at the boring parts. The boring parts are why your extension actually ships:
- Auth. Use
chrome.identity.launchWebAuthFlowto OAuth into your backend. Never store passwords in storage. - Encrypted storage.
chrome.storage.localis plaintext. If you're holding API keys for users, encrypt with a key derived from a user secret. - Quota. Track requests per user on the Worker side. AI calls are the fastest way to lose money.
- Store review. Plan a week. Chrome Web Store is faster than Apple, slower than npm. Have screenshots, a privacy policy, and a justification for every permission.
- Permissions. Ask for the minimum.
activeTab><all_urls>. Reviewers will reject otherwise.
A rejected store submission costs you a week. Read the review checklist before you write a line of code.
Distribution that actually moves the needle
Three channels, in order of how well they worked for me:
- Product Hunt — extensions do well there, especially with a 30-second video
- X (Twitter) — short demo gif, replies to posts complaining about the problem you solve
- The Web Store featured carousel — write a really good description, it gets crawled
The chrome.com/webstore organic search is also surprisingly real for niche keywords.
Where buildr fits
If you ask buildr "build me a Chrome extension that summarizes the current page," the agent picks WXT, scaffolds the popup, wires up a Worker for the AI calls, and ships both. Same chat, two artifacts (extension + backend), no separate setup.
The extension you're thinking about is shippable in a weekend.
WXT removed 80% of the boilerplate that used to make extensions painful. Manifest V3 is stable. AI gives extensions superpowers they didn't have before. If you've been sitting on an extension idea, this is the year. Tell me what you build.
Ship the extension you've been sitting on.
"Build me a Chrome extension that…" — same chat, WXT scaffold, Workers backend for AI. Free for open source.
Build my app free