Browser extensions · Updated

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

Build a Manifest V3 Chrome extension from a plain-English prompt in Claude Code, load it in Chrome, iterate with the browser integration, and prepare to monetize with Stripe and Payhook.

#claude-code#chrome-extension#manifest-v3#ai-coding#tutorial


You do not need to memorize the Chrome Extensions API to ship a working extension. Claude Code is Anthropic’s agentic coding CLI: you describe what you want, it generates manifest.json, popups, service workers, and content scripts, and you load the folder in Chrome in minutes.

This is the first hands-on tutorial on the Payhook blog. We build a small Focus Tab extension (block distracting sites for a timed session), then point you at Stripe and Payhook when you are ready to charge for Pro features.

What you will build

Focus Tab - a Manifest V3 extension that:

  • Shows a popup with a 25-minute focus timer and a start/stop button
  • Blocks configured distracting domains while a session is active
  • Persists your block list in chrome.storage.sync

No payment code in this post. Monetization comes in Monetize a browser extension without a payment backend.

Prerequisites

RequirementNotes
Claude CodeTerminal CLI (claude --version should work)
Google ChromeNeeded for loading unpacked extensions; optional Claude in Chrome for claude --chrome testing
Empty project foldere.g. ~/projects/focus-tab-extension
Claude accountPro, Max, Team, or Enterprise for Claude Code

Step 1 - Create a project folder

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

Keep all extension files in this directory. Claude Code will create and edit files here.

A short CLAUDE.md file tells Claude Code how to work in this repo on every session:

# Focus Tab - Chrome MV3 extension

- manifest_version: 3 only (no MV2)
- Use chrome.storage.sync for user settings
- Service worker: background.js (no persistent background page)
- Popup: popup.html + popup.js
- Keep permissions minimal; justify each permission in comments
- After changes, remind me to reload the extension at chrome://extensions

Create it yourself or ask Claude Code: “Add a CLAUDE.md for a Manifest V3 Chrome extension project.”

Step 3 - Start Claude Code and send the build prompt

From the project folder:

claude

Paste this prompt (edit the name or block list if you like):

Create a Chrome Manifest V3 extension called "Focus Tab" in this folder.

Requirements:
1. manifest.json with manifest_version 3, action default_popup popup.html, background service_worker background.js, permissions: storage, declarativeNetRequest (with host_permissions only if needed for blocking)
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 navigation to twitter.com, x.com, facebook.com, instagram.com, reddit.com using declarativeNetRequest or equivalent MV3 approach
4. chrome.storage.sync: save block list and session state
5. icons: create simple placeholder PNGs in icons/ (16, 48, 128) or document that I must add them
6. README.md with steps to load unpacked in Chrome

Use plain JavaScript (no bundler). Make the extension loadable immediately in chrome://extensions with Developer mode.

Claude Code will scaffold files, run commands, and fix errors iteratively. First generations sometimes need a follow-up - that is normal.

Useful follow-up prompts

  • “Fix manifest errors shown in chrome://extensions.”
  • “declarativeNetRequest rules are not blocking - debug and fix.”
  • “Add a content script that dims the page title when a session is active.”

Step 4 - Review the file structure

You should end up with something like:

focus-tab-extension/
├── CLAUDE.md
├── README.md
├── manifest.json
├── background.js
├── popup.html
├── popup.js
├── icons/
│   ├── icon16.png
│   ├── icon48.png
│   └── icon128.png
└── (optional) rules.json or scripts for declarativeNetRequest

Open manifest.json and confirm:

  • "manifest_version": 3
  • "background": { "service_worker": "background.js" }
  • "action": { "default_popup": "popup.html" }

Step 5 - Load the extension in Chrome

  1. Open chrome://extensions
  2. Enable Developer mode (top right)
  3. Click Load unpacked
  4. Select your project folder (focus-tab-extension)

If Chrome shows errors, copy the message back into Claude Code:

Chrome reports this error when loading unpacked: [paste error here]. Fix the project.

After code changes, click Reload on the extension card in chrome://extensions.

Step 6 - Test in the browser (optional but powerful)

Claude Code can pair with the Claude in Chrome extension for a build → test loop:

  1. Install Claude in Chrome and sign in with the same account as Claude Code
  2. Start a session with browser tools:
claude --chrome
  1. Inside the session, run /chrome to confirm the connection
  2. Ask Claude to test your extension, for example:
Open chrome://extensions, confirm Focus Tab is loaded, then open the popup on a normal tab and describe what you see. If anything fails, suggest a code fix.

Official troubleshooting: Use Claude Code with Chrome.

Step 7 - Iterate until it feels shippable

CheckHow
Popup opensClick the extension icon in the toolbar
Timer runsStart a session; countdown updates
Blocking worksVisit a blocked site during an active session
State survives reloadStop Chrome, reopen - settings still there

When you are happy, zip the folder for backup or push to GitHub before adding payments.

Common issues

Missing icons - Chrome requires valid paths in manifest.json. Ask Claude Code to generate minimal PNGs or add your own brand assets under icons/.

Permission errors - MV3 is strict. Prefer declarativeNetRequest with a static rules file over broad <all_urls> host permissions unless you truly need them.

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

Claude Code vs Claude chat - This tutorial uses the Code CLI in a project folder, not one-off chat snippets. The project on disk is what you load into Chrome.

Monetize next (Stripe + Payhook)

When Focus Tab should have a Pro tier (longer sessions, custom block lists, sync across devices), avoid building Stripe yourself:

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

Copy this into Claude Code for the payment pass:

Integrate Payhook into this Chrome extension as the premium unlock and payment flow.

Requirements:
- Add the Payhook UpgradeButton in the extension 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 Payhook Agent when helpful:
- Agent endpoint: https://mcp.payhook.link/
- Payhook: https://dashboard.payhook.link
- Deliver: manifest permissions, background PayhookClient setup, popup UpgradeButton, and Pro feature gating wired to live payment state.

Next steps

Questions while building? Payhook and docs cover the payment path once your extension works in Chrome.