Skip to content

Firefox (AMO)

Firefox distribution goes through addons.mozilla.org (AMO). The kit builds a Firefox-specific package (with the Chromium-only permissions and APIs filtered out) from the same codebase.

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 signing/submitting, set your own add-on ID in wxt.config.ts; the Firefox manifest branch carries browser_specific_settings.gecko.id with a placeholder (extension@extensionstart.com) and a TODO to replace it.

What’s 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 the offscreen auth fallback is unavailable: Google sign-in on Firefox requires WXT_GOOGLE_OAUTH_CLIENT_ID (the web-auth-flow path; see the sign-in guide).
  • Chrome-only APIs are guarded in code (browser.sidePanel?.…).

AMO reviews are human and stricter than CWS about build pipelines. Because the kit’s code is bundled and minified (Vite/WXT), you must upload the source code alongside the extension zip, plus instructions that let a reviewer reproduce the build byte-for-byte.

wxt zip -b firefox (the zip:firefox script) produces both zips in apps/extension/.output/: the extension package and a -sources.zip containing the source tree. Upload the sources zip when the AMO submission flow asks “Do you need to submit source code?” → Yes.

Paste into the “Notes for Reviewers” field 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 login via the kit’s email auth is the easiest to hand a reviewer).

  • Versions are immutable: you can’t replace an uploaded version. Fix and bump.
  • The kit’s CI already runs AMO’s linter (addons-linter) against the Firefox build, so lint-class surprises should be caught before you submit.
  • Data collection requires the same disclosure discipline as CWS; AMO asks for a privacy policy whenever data leaves the machine (auth and error reports both qualify; reuse the privacy disclosures content).
  • Updates are auto-published after review; there is no staged rollout on AMO.