Skip to content

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.

Terminal window
pnpm build:firefox # local test build
pnpm zip:firefox # AMO upload zips

Load 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; offscreen and sidePanel don’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?.…).

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.

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 sources
2. pnpm install --frozen-lockfile
3. pnpm zip:firefox
4. 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).

  • 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.