How to Publish a Firefox Extension to addons.mozilla.org (2026 Guide)
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
| Step | Action |
|---|---|
| 1 | Create or sign in with a Mozilla account on AMO |
| 2 | Set a display name on your AMO developer profile |
| 3 | Add browser_specific_settings.gecko.id (and data collection declarations for new extensions) |
| 4 | Build a production zip (MV3 recommended; max 200 MB) |
| 5 | Run web-ext lint locally |
| 6 | Developer Hub: choose listed vs self-distributed, upload zip |
| 7 | Upload source package if minified or bundled |
| 8 | Complete listing metadata, privacy policy, reviewer notes |
| 9 | Submit version; wait for signing and possible review |
| 10 | Optional: 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 wiring | Publish to Firefox Add-ons |
| Chrome or Edge first | Chrome Web Store guide, Edge Add-ons guide |
| Which TurboStarter kit includes an extension | Which kit to choose |
| Pre-flight store accounts and assets | Publishing 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).
- 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.
| Distribution | User experience | Updates |
|---|---|---|
| Public listing on AMO | Discoverable on AMO and in Firefox Add-ons Manager; SEO on AMO | Firefox checks AMO for updates when you upload new listed versions |
| Self-distributed ("unlisted") | Not publicly browsable on AMO; you host the signed .xpi or link | You 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/extensionAddress 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
- Sign in at the Add-ons Developer Hub.
- Click Submit Your First Add-on or Submit a New Add-on (submitting an add-on).
- Choose distribution:
- On this site for a public (or experimental) AMO listing.
- On your own for self-distributed signing.
Upload and validation
- On Upload Version, click Select a file and choose your
.zip,.xpi, or.crx(submitting an add-on). - Wait for the validator. Fix hard failures before Continue.
- Select compatible platforms (desktop and/or Android when applicable).
- 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):
| Field | Notes |
|---|---|
| Name, summary, description | Shown on AMO; keep summary scannable |
| Add-on URL slug | Must be unique on AMO |
| Categories | Up to two Firefox desktop and two Android categories |
| Support email / site | Required for user trust |
| License | Pick from AMO's license list |
| Privacy policy | Required when any data is transmitted off-device |
| Payment / hardware flags | Disclose if full functionality needs paid services |
| Notes for reviewers | Test 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):
- Automated validation on upload (permissions, manifest, known malware patterns).
- Content review of listing text and metadata.
- Technical code review for policy compliance.
- 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:
| Issue | Mitigation |
|---|---|
| Undisclosed data collection | Align data_collection_permissions, privacy policy, and runtime behavior |
| Overbroad permissions | Drop unused permissions / host_permissions; document what remains |
| Minified code without source | Upload 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 functionality | Use 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 listedUse --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):
- Run Mozilla's compatibility tools in Developer Hub or compare APIs against Chrome incompatibilities.
- Prefer the
browser.*namespace (Promises) via WXT; Firefox also supports callback-stylechrome.*for most APIs (porting guide). - Move host permissions to
host_permissionsfor MV3 (MV3 migration guide). - Remove Chrome-only manifest keys (
externally_connectable, Chromeoauth2,update_urlpointing at Google). - Add
browser_specific_settings.gecko.idand currentdata_collection_permissionsfor new listings. - Test with
web-ext runorabout: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).
| Store | Registration cost (documented) | TurboStarter doc |
|---|---|---|
| Chrome Web Store | One-time Google fee (Chrome guide) | Publish to Chrome |
| Firefox Add-ons | No registration fee | Publish to Firefox |
| Microsoft Edge Add-ons | No 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.jsonbefore 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
Yes. Registering a developer account on Firefox Add-ons does not require a registration fee (Firefox publishing docs, developer accounts). You still pay for your own hosting, CI, and any SaaS infrastructure outside Mozilla.
Sign in at the Add-ons Developer Hub and start Submit a New Add-on (submitting an add-on). That is the correct entry point for both listed and self-distributed signing.
Listed extensions are public on AMO and installable from the Add-ons Manager. Self-distributed extensions are signed by Mozilla but not publicly listed; you distribute the signed package yourself and may use update_url for updates (signing overview, self-distribution).
Build a zip with manifest.json at the root, run web-ext lint, then upload through Developer Hub or sign with web-ext sign / the AMO API (submitting an add-on, web-ext command reference).
Mozilla states automated signing and publication can take up to 24 hours, or longer if your submission is selected for manual review (signing overview). Plan release comms with that window in mind.
AMO does not process in-store purchases. Disclose when full functionality requires paid services using the listing checkbox for payment or non-free services (submitting an add-on). Most SaaS teams monetize on the web app, not inside the add-on install flow.
Audit Chrome-only APIs and manifest keys, add browser_specific_settings.gecko.id, adopt Firefox data collection declarations for new extensions, test with web-ext, then submit to AMO (porting a Google Chrome extension, MV3 migration guide).
No. Manual Developer Hub upload is enough for the first release. Use web-ext sign or wxt submit when you want scripted signing and updates with JWT credentials (Firefox publishing docs).
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.
How to Publish an Extension to Microsoft Edge Add-ons (2026)
Publish an edge extension on Microsoft Edge Add-ons: Partner Center developer account, MV3 zip, listing assets, certification, updates, and API automation.
Renovate vs Dependabot - best tool to automate your dependency updates (2026)
Which should you pick for a monorepo in 2026? Compare Renovate and Dependabot on features, monorepo support, and automation.



