10+ AI SaaS templates for web & mobile
home

How to Publish a Firefox Extension to addons.mozilla.org (2026 Guide)

·16 min read

How to publish a Firefox extension: AMO developer account, listed vs self-distributed signing, MV3 package prep, review, web-ext sign, updates, and Chrome porting.

You built a WebExtension. The next job is to publish a Firefox extension so release-channel Firefox users can install a signed build from addons.mozilla.org (AMO) or from your own update channel. Mozilla runs account registration, automated validation, signing, listing review, and distribution even when your SaaS billing lives on Stripe or Lemon Squeezy.

Search Console already sends turbostarter.dev hundreds of impressions for Firefox publishing queries, mostly to our Firefox publishing docs. This post is the broader, tool-agnostic walkthrough those docs complement. If you are shipping web, mobile, and extension from one monorepo, pair it with cross-platform SaaS architecture and versioning across surfaces.

Short answer

To publish a Firefox extension, register on addons.mozilla.org with a Mozilla account (no AMO registration fee), open the Add-ons Developer Hub, upload a .zip with manifest.json at the root, choose listed on AMO or self-distributed (unlisted), complete metadata and any source-code upload, then submit. Mozilla signs every build; automated validation runs first, and manual review can follow. It can take up to 24 hours to be signed and published, or longer if selected for manual review (signing overview). After the first manual submission, automate with web-ext sign or the AMO Add-on API.

TL;DR checklist

StepAction
1Create or sign in with a Mozilla account on AMO
2Set a display name on your AMO developer profile
3Add browser_specific_settings.gecko.id (and data collection declarations for new extensions)
4Build a production zip (MV3 recommended; max 200 MB)
5Run web-ext lint locally
6Developer Hub: choose listed vs self-distributed, upload zip
7Upload source package if minified or bundled
8Complete listing metadata, privacy policy, reviewer notes
9Submit version; wait for signing and possible review
10Optional: create JWT API credentials and wire CI (wxt submit)

Who this guide is for

You have a working extension (popup, content scripts, background, or all three) and you want it installable in release Firefox, not only temporary loads in about:debugging. You might already ship on the Chrome Web Store or Microsoft Edge Add-ons. Each store is a separate listing. TurboStarter's extension kit docs cover auth and deployment; this article focuses on Mozilla's publishing pipeline.

You need…Start here
Kit-specific zip + GitHub Actions wiringPublish to Firefox Add-ons
Chrome or Edge firstChrome Web Store guide, Edge Add-ons guide
Which TurboStarter kit includes an extensionWhich kit to choose
Pre-flight store accounts and assetsPublishing checklist

Firefox Add-ons developer account (Developer Hub)

Registration cost and Mozilla account

Developer accounts on AMO are tied to a Mozilla account (developer accounts). Unlike the Chrome Web Store, Firefox Add-ons does not charge a registration fee (Firefox publishing docs).

On addons.mozilla.org:

  • If you already have a Mozilla account, click Log in in the header.
  • Otherwise click Register, confirm your email, then return to AMO.

Publishing workflows live in the Add-ons Developer Hub (addons.mozilla.org/developers/). That hub is what people mean when they search for the Firefox add-ons developer hub or Mozilla add-ons developer hub.

Display name and email deliverability

Mozilla asks you to set a display name on your AMO profile. It does not sync automatically from your Mozilla account display name (developer accounts). Reviewers and users see this name on listings and communication.

If AMO emails do not arrive, Extension Workshop lists checks: correct primary email on the Mozilla account, spam folders, inbox capacity, and provider filters (developer accounts).

Blocked or restricted accounts

Mozilla may block accounts that use disposable email addresses or that submitted multiple policy-violating add-ons (developer accounts). If you believe a block is wrong, use the appeal link in Mozilla's notification email.

Listed on AMO vs self-distributed (unlisted)

Every extension installed in release or beta Firefox must be signed by Mozilla (signing overview). You still choose how users discover it.

DistributionUser experienceUpdates
Public listing on AMODiscoverable on AMO and in Firefox Add-ons Manager; SEO on AMOFirefox checks AMO for updates when you upload new listed versions
Self-distributed ("unlisted")Not publicly browsable on AMO; you host the signed .xpi or linkYou supply an update_url in browser_specific_settings.gecko if you want Firefox to auto-update (self-distribution)

Both paths use the same Developer Hub upload flow at the start. On this site continues to the AMO listing wizard. On your own follows the self-distribution signing flow (submitting an add-on).

Self-distributed builds are still subject to Mozilla Add-on Policies and can be manually reviewed after signing (signing overview).

Signing methods and which distribution channels they support are documented in Mozilla's table for web upload, web-ext sign, Add-on Create API (V5), and Signing API (V4) (signing overview).

Prepare your extension package

Manifest V3 vs Manifest V2 in Firefox

Manifest V3 is generally available in Firefox 109+ (MV3 migration guide). New extensions should target MV3 with "manifest_version": 3.

Firefox's MV3 implementation intentionally diverges from Chromium in places (non-persistent background pages instead of service workers, retained page_action, stricter CSP rules, and more). Read Mozilla's migration checklist before you assume Chrome-only MV3 patterns work unchanged (MV3 migration guide).

TurboStarter's WXT-based extension app builds Firefox targets alongside Chrome. Local dev docs reference loading from apps/extension/build/firefox-mv2 for temporary installs (extension development); production store zips come from your pnpm / WXT build output (see Publish to Firefox).

browser_specific_settings.gecko.id

Mozilla requires an add-on ID to publish. Set it in manifest.json:

"browser_specific_settings": {
  "gecko": {
    "id": "addons@example.com",
    "strict_min_version": "109.0"
  }
}

Use an email-style ID you control, or another stable string allowed by Mozilla. The ID anchors signing, API credentials, and (for self-distribution) update manifests. If you rename applications from older tutorials, Mozilla now expects browser_specific_settings (MV3 migration guide).

For self-distributed auto-updates, also set update_url under gecko to your update manifest (self-distribution).

Data collection permissions (new extensions)

Firefox 140+ (desktop) and 142+ (Android) ship built-in consent for data collection and transmission (built-in data consent).

From November 3, 2025, all new extensions must declare what they collect using browser_specific_settings.gecko.data_collection_permissions in manifest.json. Extensions created before that date are not forced on every update yet, but Mozilla plans to require adoption later (built-in data consent).

If you collect nothing off-device, declare:

"data_collection_permissions": {
  "required": ["none"]
}

If you transmit personal or technical data categories, map them to Mozilla's taxonomy (locationInfo, browsingActivity, technicalAndInteraction, and others) in required and/or optional arrays (built-in data consent). A privacy policy remains required when data leaves the user's device (submitting an add-on).

Zip layout, size, and web-ext build

Package the extension files at the zip root, not a folder wrapper (package your extension). Maximum upload size is 200 MB (submitting an add-on).

Prefer web-ext build to exclude .git and other junk. Example after a WXT production build:

cd apps/extension/.output/firefox-mv3
zip -r ../firefox-amo.zip . -x "*.map"

TurboStarter maps package.json version into the manifest on build (extension versioning recipe). Firefox accepts version strings of 1 to 4 dot-separated numeric segments with up to 9 digits per segment (MV3 migration guide).

Source code submission

If your upload contains minified, transpiled, or otherwise hard-to-read code, Mozilla expects a source code package with build instructions (source code submission). The Developer Hub asks explicitly whether source is required during upload (submitting an add-on).

Ship readable source, a README for reviewers, and the exact commands to reproduce the uploaded bundle. Omit secrets and private keys.

Lint before upload

Run Mozilla's validator locally:

npx web-ext lint --source-dir ./path/to/extension

Address errors before upload. Warnings may still allow submission, but security and privacy warnings often predict review trouble (submitting an add-on, Firefox publishing docs).

Submit a Firefox extension step by step

Start submission in Developer Hub

  1. Sign in at the Add-ons Developer Hub.
  2. Click Submit Your First Add-on or Submit a New Add-on (submitting an add-on).
  3. Choose distribution:
    • On this site for a public (or experimental) AMO listing.
    • On your own for self-distributed signing.

Upload and validation

  1. On Upload Version, click Select a file and choose your .zip, .xpi, or .crx (submitting an add-on).
  2. Wait for the validator. Fix hard failures before Continue.
  3. Select compatible platforms (desktop and/or Android when applicable).
  4. Answer whether you must upload source code; attach the source zip if yes.

Listing metadata (listed extensions)

On Describe Add-on, complete (submitting an add-on):

FieldNotes
Name, summary, descriptionShown on AMO; keep summary scannable
Add-on URL slugMust be unique on AMO
CategoriesUp to two Firefox desktop and two Android categories
Support email / siteRequired for user trust
LicensePick from AMO's license list
Privacy policyRequired when any data is transmitted off-device
Payment / hardware flagsDisclose if full functionality needs paid services
Notes for reviewersTest accounts, feature flags, source build notes

Check This add-on is experimental only when you want reduced visibility during beta.

Click Submit Version. Listed add-ons can appear on AMO after signing while a deeper review continues (submitting an add-on).

Self-distributed signing flow

After validation, self-distributed uploads enter Version Signature Pending. Mozilla emails when signing completes. Download the signed file from My Add-ons before you distribute it (submitting an add-on).

Firefox extension review: what gets flagged

Mozilla's pipeline includes (Firefox publishing docs, signing overview):

  1. Automated validation on upload (permissions, manifest, known malware patterns).
  2. Content review of listing text and metadata.
  3. Technical code review for policy compliance.
  4. Basic functionality testing against the description.

Timing: signing and publication can take up to 24 hours, or longer when manual review is queued (signing overview). Mozilla does not publish a shorter guaranteed SLA in that doc.

Common rejection themes:

IssueMitigation
Undisclosed data collectionAlign data_collection_permissions, privacy policy, and runtime behavior
Overbroad permissionsDrop unused permissions / host_permissions; document what remains
Minified code without sourceUpload a complete source package and build docs
Policy mismatch (deceptive listing, affiliate spam, remote code)Read Add-on Policies; fix listing and code
Broken core functionalityUse Notes for Reviewers with test credentials (marketing guidelines)

Rejections email the developer and show on the add-on Status page (Firefox publishing docs). Fix issues, bump version, upload a new package, and submit again. See publishing troubleshooting.

Update an existing Firefox extension

Upload updates on the same AMO add-on page so Mozilla treats the file as a new version, not a duplicate product (submitting an add-on).

Every upload needs a higher manifest version than the last accepted build. TurboStarter's extension updates doc recommends bumping package.json first.

If you add permissions or change data collection declarations, expect another review cycle and possible listing edits.

Automate with web-ext sign and the AMO API

The first submission should be manual so you have a stable extension ID, listing slug, and reviewer context before CI takes over (Firefox publishing docs).

JWT API keys

Create credentials at Mozilla API keys (JWT issuer + secret). Store them as GitHub Actions secrets:

env:
  FIREFOX_EXTENSION_ID: ${{ secrets.FIREFOX_EXTENSION_ID }}
  FIREFOX_JWT_ISSUER: ${{ secrets.FIREFOX_JWT_ISSUER }}
  FIREFOX_JWT_SECRET: ${{ secrets.FIREFOX_JWT_SECRET }}

TurboStarter documents these in .github/workflows/publish-extension.yml (Publish to Firefox). Plasmo's BMS Firefox token guide walks through credential setup.

web-ext sign in CI

Modern web-ext (v8+) can create listings and upload updates via AMO API v5 when configured with JWT credentials (web-ext command reference):

web-ext sign \
  --api-key "$FIREFOX_JWT_ISSUER" \
  --api-secret "$FIREFOX_JWT_SECRET" \
  --id "$FIREFOX_EXTENSION_ID" \
  --channel listed

Use --channel unlisted for self-distributed builds. Pass --upload-source-code when reviewers need a source archive (web-ext command reference).

npx wxt submit wraps the same stores when you configure Firefox secrets (WXT submit).

Automation limits

Automated upload can still fail review if required listing fields are empty or if you introduce breaking permission changes. Update AMO metadata manually when the extension's capabilities change (Firefox publishing docs).

Port a Chrome extension to Firefox

Most Chrome MV3 extensions port with modest edits (porting a Google Chrome extension):

  1. Run Mozilla's compatibility tools in Developer Hub or compare APIs against Chrome incompatibilities.
  2. Prefer the browser.* namespace (Promises) via WXT; Firefox also supports callback-style chrome.* for most APIs (porting guide).
  3. Move host permissions to host_permissions for MV3 (MV3 migration guide).
  4. Remove Chrome-only manifest keys (externally_connectable, Chrome oauth2, update_url pointing at Google).
  5. Add browser_specific_settings.gecko.id and current data_collection_permissions for new listings.
  6. Test with web-ext run or about:debugging, then lint and sign.

Chrome and Edge store listings do not transfer to AMO. You still ship three listings if you want full browser coverage (Chrome guide, Edge guide).

Can you charge for a Firefox add-on?

AMO does not sell paid add-ons or in-store subscriptions the way mobile app stores do. Mozilla instead asks whether your add-on requires payment, non-free services or software, or additional hardware for full functionality (submitting an add-on). Check that box when users must pay you (or a third party) outside the extension.

The common SaaS pattern matches Chrome and Edge: the extension is free to install, and you bill on the web app with Stripe, Lemon Squeezy, or similar. Be explicit in the listing description and privacy policy about what data flows to your backend.

Mozilla's policies still prohibit deceptive paywalls and undisclosed paid behavior (Add-on Policies).

Also ship to Chrome and Microsoft Edge

Each marketplace keeps its own account, review, and URL. Shared engineering wins come from one WXT codebase and aligned versioning (software versioning across surfaces).

StoreRegistration cost (documented)TurboStarter doc
Chrome Web StoreOne-time Google fee (Chrome guide)Publish to Chrome
Firefox Add-onsNo registration feePublish to Firefox
Microsoft Edge Add-onsNo registration fee (Edge guide)Publish to Edge

See the Chrome + Firefox + Edge starter kit and WXT + Vite extension stack for how TurboStarter structures multi-browser builds.

How TurboStarter fits in

TurboStarter Core is a production-ready SaaS starter kit across Next.js web, Expo mobile, and a WXT browser extension on one Better Auth backend. Publishing is not a separate product: you get Firefox, Chrome, and Edge build targets, shared API types, and docs that mirror the steps in this article.

What the kit documents today:

  • Manual and automated Firefox publishing, including JWT secrets and GitHub Actions (Firefox Add-ons).
  • Parallel Chrome and Edge guides (Chrome blog, Edge blog).
  • Pre-submission checklist for API URLs, assets, and store accounts (publishing checklist).
  • Version bumps via package.json before each store upload (updates).

Use this post for policy context and official Mozilla links. Use /docs/extension/publishing/firefox when you are inside the repo running builds and workflows. If you are evaluating kits, see Core pricing.

FAQ

Sounds good?Now let's make it real. In minutes.
Try TurboStarter

Takeaway

Publish a Firefox extension by treating AMO as its own release channel: register with a Mozilla account (no AMO fee), declare data collection for new listings, ship a clean MV3 zip with a stable gecko.id, choose listed vs self-distributed deliberately, and plan for signing and review that may take a day or more. Automate only after the first manual submission passes. If you want the extension client already wired to your SaaS backend, TurboStarter Core ships the WXT app, Firefox docs, and CI patterns so you can focus on the product inside the popup, not on rediscovering Developer Hub labels every release.

world map
Community

Connect with like-minded people

Join our community to get feedback, support, and grow together with 1,000+ builders on board, let's ship it!

Join us

Ship your startup everywhere. In minutes.

Don't burn tokens on setup and start building features on day one.

Get TurboStarter