Firefox (AMO)
Firefox distribution goes through addons.mozilla.org (AMO). The kit builds a Firefox-specific package from the same codebase, with the Chromium-only permissions and APIs filtered out.
Build and package
Section titled “Build and package”pnpm build:firefox # local test buildpnpm zip:firefox # AMO upload zipsLoad a test build via about:debugging → This Firefox → Load Temporary
Add-on. Before submitting, set your own add-on ID in wxt.config.ts;
the Firefox manifest branch carries a placeholder
browser_specific_settings.gecko.id with a TODO to replace it.
What is different in the Firefox build (handled per-browser in
wxt.config.ts):
- Permissions are filtered to
storage,tabs,identity,alarms;offscreenandsidePaneldon’t exist on Firefox and AMO lint rejects unknown permissions. - No offscreen document means Google sign-in on Firefox requires
WXT_GOOGLE_OAUTH_CLIENT_ID(the web-auth-flow path; see Sign-in). - Chrome-only APIs are guarded in code (
browser.sidePanel?.…).
Upload source code with the zip
Section titled “Upload source code with the zip”AMO reviews are human and stricter than CWS about build pipelines. Because the code is bundled and minified, you must upload the source code alongside the extension zip, plus instructions that reproduce the build.
pnpm zip:firefox produces both zips in apps/extension/.output/:
the extension package and a -sources.zip with the source tree. Upload
the sources zip when the AMO flow asks “Do you need to submit source
code?” → Yes.
Reviewer notes template
Section titled “Reviewer notes template”Paste into “Notes for Reviewers” and adjust versions:
This extension is built from the included sources with WXT (Vite).
Build environment:- Node 22, pnpm 8 (pinned via the packageManager field in package.json)
Reproduce the build:1. unzip the sources2. pnpm install --frozen-lockfile3. pnpm zip:firefox4. compare .output/*-firefox.zip with the submitted package
Notes:- No remote code: all executed JS ships in the bundle. Remote requests fetch JSON data only (feature flags, announcements) from our own Firebase backend.- Minification is Vite's standard esbuild pass; no obfuscation.- Sign-in uses browser.identity.launchWebAuthFlow with Firebase Auth (OAuth implicit flow; no client secret in the bundle).If you kept billing: add one line saying premium features require a subscription and include a test account (email/password sign-in is the easiest to hand a reviewer).
AMO-specific gotchas
Section titled “AMO-specific gotchas”- Versions are immutable: you can’t replace an uploaded version. Fix and bump.
- CI already runs AMO’s linter (
addons-linter) against the Firefox build, so lint-class surprises surface before you submit. - AMO asks for a privacy policy whenever data leaves the machine (auth and error reports both qualify); reuse the privacy disclosures content.
- Updates auto-publish after review; there is no staged rollout on AMO.