Browser extensions · Updated

Create your first Firefox extension with Claude Code (step-by-step tutorial)

Build a Manifest V3 Firefox add-on from a plain-English prompt in Claude Code, load it via about:debugging, fix gecko compatibility, and prepare Pro monetization with Stripe and Payhook.

#claude-code#firefox#manifest-v3#webextensions#tutorial


Firefox add-ons use the same WebExtensions model as Chrome, but loading, IDs, and a few APIs differ. Claude Code handles those details when you prompt clearly - this tutorial walks through building Focus Tab (a timed site blocker) for Firefox, then points you at Payhook when you are ready to sell Pro.

If you prefer a no-code brief, start with Create a Firefox extension without coding.

What you will build

Focus Tab for Firefox - a Manifest V3 add-on that:

  • Shows a popup with a 25-minute focus timer and start/stop controls
  • Blocks configured distracting domains while a session is active
  • Persists settings in browser.storage.sync (Firefox’s WebExtensions namespace)
  • Includes browser_specific_settings.gecko so AMO and temporary loads accept the add-on

No payment code in this post. Monetization comes in Monetize a browser extension without a payment backend - the same Payhook flow works in Firefox.

Prerequisites

RequirementNotes
Claude CodeTerminal CLI (claude --version)
FirefoxFor about:debugging temporary loads
Empty project foldere.g. ~/projects/focus-tab-firefox
Claude accountPro, Max, Team, or Enterprise for Claude Code

Step 1 - Create a project folder

mkdir -p ~/projects/focus-tab-firefox
cd ~/projects/focus-tab-firefox

Step 2 - Add context with CLAUDE.md

# Focus Tab - Firefox MV3 WebExtension

- manifest_version: 3 only
- Use browser.storage.sync (or webextension-polyfill with browser namespace)
- Service worker: background.js
- Popup: popup.html + popup.js
- Include browser_specific_settings.gecko with a unique id (email-style)
- Target Firefox 109+; keep permissions minimal
- After changes, remind me to reload via about:debugging

Ask Claude Code: “Add a CLAUDE.md for a Firefox Manifest V3 WebExtension project.”

Step 3 - Start Claude Code and send the build prompt

claude

Paste this prompt:

Create a Firefox WebExtension (Manifest V3) called "Focus Tab" in this folder.

Requirements:
1. manifest.json with manifest_version 3, browser_specific_settings.gecko id "focus-tab@example.com", action default_popup popup.html, background service_worker background.js, permissions: storage, declarativeNetRequest (host_permissions only if needed)
2. popup.html + popup.js: 25-minute focus timer UI, Start and Stop buttons, show remaining time
3. background.js: when a focus session is active, block twitter.com, x.com, facebook.com, instagram.com, reddit.com using declarativeNetRequest or equivalent MV3 approach
4. browser.storage.sync: save block list and session state
5. Use the browser.* API namespace (not chrome.*) or include webextension-polyfill
6. icons: placeholder PNGs in icons/ (16, 48, 128)
7. README.md with steps to load via about:debugging → This Firefox → Load Temporary Add-on

Plain JavaScript, no bundler. Must load immediately in Firefox.

Useful follow-up prompts

  • “Fix manifest errors from about:debugging when loading temporary add-on.”
  • “Add gecko strict_min_version and data_collection_permissions if Firefox warns about them.”
  • “Make this codebase also load in Chrome with the smallest diff.”

Step 4 - Review the file structure

focus-tab-firefox/
├── CLAUDE.md
├── README.md
├── manifest.json
├── background.js
├── popup.html
├── popup.js
├── icons/
└── (optional) rules.json

Confirm in manifest.json:

  • "manifest_version": 3
  • "browser_specific_settings": { "gecko": { "id": "focus-tab@example.com", ... } }
  • "background": { "service_worker": "background.js" }

Change the gecko id to something you own before publishing to AMO.

Step 5 - Load the add-on in Firefox

  1. Open Firefox and go to about:debugging
  2. Click This Firefox in the sidebar
  3. Click Load Temporary Add-on…
  4. Select manifest.json in your project folder

If Firefox shows errors, paste them into Claude Code:

Firefox reports this error when loading temporary add-on: [paste error]. Fix the project.

After code changes, click Reload on the add-on card in about:debugging.

Temporary add-ons disappear when Firefox restarts. That is expected until you publish to AMO.

Step 6 - Test in the browser

CheckHow
Popup opensClick the toolbar icon
Timer runsStart a session; countdown updates
Blocking worksVisit a blocked site during an active session
State survives reloadRestart Firefox - settings should persist via storage

Firefox-specific issues

Missing gecko ID - Firefox requires browser_specific_settings.gecko.id for signing and updates. Use a unique email-style string you control.

chrome.* vs browser.* - Firefox supports many chrome.* aliases, but prefer browser.* or webextension-polyfill for cross-browser code.

Service worker sleep - Long timers may need browser.alarms instead of setInterval. Prompt: “Move the focus timer to browser.alarms so it survives service worker sleep in Firefox.”

DeclarativeNetRequest - Supported in recent Firefox; if rules fail, ask Claude to verify declarative_net_request permission and static rules file format.

Ship to AMO (when ready)

See Publish a Firefox extension to AMO for zipping, developer account setup, and review tips.

Monetize next (Stripe + Payhook)

When Focus Tab should have a Pro tier:

  1. Connect Stripe in dashboard.payhook.link
  2. Read Stripe Connect for extension builders
  3. Add unlock flow with Monetize a browser extension without a payment backend

Copy into Claude Code:

Integrate Payhook into this Firefox WebExtension as the premium unlock flow.

Requirements:
- Add the Payhook UpgradeButton in the popup for paid tiers
- Gate Pro features with Payhook entitlement checks (no custom license server)
- Open hosted Stripe checkout via unlock.payhook.link - do not build a custom Stripe backend
- Use browser.* APIs compatible with Firefox

Payhook: https://dashboard.payhook.link
MCP: https://mcp.payhook.link

Next steps