[Extension Name]
A Manifest V3 browser extension. Popup, options page, content script, background worker. TypeScript end to end.
Source of truth
GitHub. Versioned zips uploaded to Chrome Web Store via web-ext sign (also works for Firefox). The current store version is the source of truth for what users have.
Tech stack
Vite 6 (with @crxjs/vite-plugin for MV3 HMR) + TypeScript + React 19 (for the popup + options pages). Tailwind v4. Manifest V3. Storage via chrome.storage.local. Cross-browser polyfilled via webextension-polyfill.
Deploy
npm run build-> outputs todist/cd dist && zip -r ../extension.zip .- Upload to Chrome Web Store Developer Dashboard
- (Optional)
web-ext sign --api-key=$AMO_KEY --api-secret=$AMO_SECRETfor Firefox AMO
File map
src/manifest.tsdeclarative manifest (compiled to JSON by crxjs)src/background.tsMV3 service worker (event-driven, NOT persistent)src/content/content scripts injected per-sitesrc/popup/React popupsrc/options/React options pagesrc/lib/storage.tstypedchrome.storagewrappersrc/lib/messaging.tscontent <-> background message typesvite.config.tswith@crxjs/vite-pluginpublic/icons/16/32/48/128 PNG icons
.env keys
None at runtime (MV3 has no env injection). Build-time variables can be passed via Vite define.
Hard rules
- MV3 background is a service worker. It can be killed at any time. Persist anything via
chrome.storage, not module-level variables. - Content scripts run in an isolated world. They cannot read the page's JS scope without injecting a script tag.
host_permissionsshould be the minimum needed. Users see them at install. Asking for "all sites" tanks adoption.- All cross-context messaging is typed via
src/lib/messaging.ts. No rawchrome.runtime.sendMessagecalls. - Store icons must be 16x16, 32x32, 48x48, 128x128 PNG. Inkscape -> PNG export.
- Privacy policy URL required for any extension that handles user data.
Recent significant changes
- 2026-05-02: Scaffolded. Locked: Vite + crxjs (HMR matters), React for popup (consistency with rest of stack), webextension-polyfill for Firefox parity.
Next session: start here
- Edit
src/manifest.tsname, description, host_permissions. - Generate icons (Figma export or
realfavicongenerator.netadapted). npm run dev-> Vite watches, crxjs hot-reloads the unpacked extension.- Load
dist/as unpacked extension atchrome://extensions. - Test on real sites before submitting to store.