Browser extensions · Updated

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

Build a Safari Web Extension on macOS with Claude Code, from manifest and popup to Xcode wrapper, Safari Settings, and Payhook-ready Pro monetization with hosted Stripe checkout.

#claude-code#safari#macos#web-extension#tutorial


Safari extensions on Mac use Safari Web Extensions - WebExtension files (manifest.json, popup, service worker) wrapped in a minimal Xcode app so Safari can install them. Claude Code can generate both the web extension layer and the Xcode scaffolding when you describe the product clearly.

This tutorial builds Focus Tab for Safari (timed site blocking), then links to Payhook for Pro revenue. For a lighter no-code path, see Create a Safari extension without coding.

What you will build

Focus Tab for Safari - a Safari Web Extension that:

  • Shows a popup with a 25-minute focus timer
  • Blocks distracting domains during an active session
  • Persists settings via extension storage APIs
  • Runs inside a macOS app target you open in Xcode and enable in Safari Settings

Payment wiring is a separate pass: Monetize a browser extension without a payment backend applies to Safari Web Extensions too.

Prerequisites

RequirementNotes
Mac with macOSSafari Web Extensions are built and tested on Mac
XcodeFree from the Mac App Store; required for the wrapper app
Claude CodeTerminal CLI in your project folder
Apple IDFor local signing; Apple Developer Program for App Store distribution
Firefox or Chrome optionalSame WebExtension core can be reused across browsers

Step 1 - Create a project folder

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

Step 2 - Add context with CLAUDE.md

# Focus Tab - Safari Web Extension (macOS)

- WebExtension layer: manifest_version 3, popup, service worker
- Xcode: Safari Web Extension App target with embedded extension resources
- Minimal permissions; explain each in README
- Test flow: build/run in Xcode → Safari → Settings → Extensions → enable
- Pro monetization will use Payhook hosted checkout (not in-popup cards)
- After web changes, remind me to rebuild in Xcode and reload in Safari

Step 3 - Start Claude Code and send the build prompt

claude

Paste this prompt (adjust names as needed):

Create a Safari Web Extension for macOS called "Focus Tab" in this folder.

WebExtension requirements (Manifest V3):
1. manifest.json with action default_popup popup.html, background service_worker background.js, permissions: storage, declarativeNetRequest as needed
2. popup.html + popup.js: 25-minute focus timer, Start/Stop, show remaining time
3. background.js: block twitter.com, x.com, facebook.com, instagram.com, reddit.com during an active focus session
4. Persist block list and session state in extension storage
5. icons/ with 16, 48, 128 placeholders

Xcode requirements:
6. Generate or document a Safari Web Extension App project structure that embeds the WebExtension files
7. README.md with exact steps for my macOS version: open in Xcode, select scheme, Run on My Mac, enable extension in Safari → Settings → Extensions
8. Plain JavaScript, no bundler for the extension scripts

Assume I am not a Swift developer - keep native code minimal and commented.

Claude Code may create a folder layout like:

focus-tab-safari/
├── CLAUDE.md
├── README.md
├── Focus Tab/              # Xcode project (names vary)
│   └── ...
└── Extension/              # or Resources/ - WebExtension root
    ├── manifest.json
    ├── background.js
    ├── popup.html
    ├── popup.js
    └── icons/

If Claude only generates web files, follow up:

Add the minimal Xcode Safari Web Extension App wrapper so I can run this on my Mac and enable it in Safari Settings.

Step 4 - Open in Xcode and run on your Mac

Exact menu labels shift between Xcode versions; use the README Claude generated. Typical flow:

  1. Open the .xcodeproj or .xcworkspace in Xcode
  2. Select the Safari Web Extension app scheme (not a unit test target)
  3. Choose My Mac as the run destination
  4. Click Run (▶) - Xcode installs the containing app
  5. Open Safari → Settings → Extensions
  6. Enable Focus Tab and allow permissions on a test site
  7. Click the toolbar icon to open the popup

Paste Xcode or Safari errors back to Claude Code:

Xcode build failed with: [paste error]. Fix the Safari Web Extension project.

Step 5 - Test the extension

CheckHow
Extension appears in Safari SettingsListed and toggle on
Popup opensToolbar icon on a normal page
Timer runsStart session; UI updates
Blocking worksVisit a blocked domain during a session
Rebuild after web editsRun again in Xcode; reload extension if needed

Safari caches extension bundles. If changes do not show, disable and re-enable the extension in Settings or clean the build folder in Xcode (Product → Clean Build Folder).

Safari-specific issues

Code signing - Local testing uses your Apple ID team. For distribution, enroll in the Apple Developer Program.

API differences - Safari Web Extensions support most MV3 APIs but not every Chrome flag. Prompt: “Replace unsupported APIs with Safari-compatible alternatives and document limitations in README.”

App Store vs direct - Mac App Store distribution goes through App Review; hosted Payhook checkout keeps card data out of your popup (helpful for review narratives). See Publish a Safari extension to the Mac App Store.

Cross-browser reuse - The same manifest.json core often loads in Chrome and Firefox with small diffs. Ask Claude: “Extract shared WebExtension files and add a Firefox gecko id without breaking the Safari wrapper.”

Monetize next (Stripe + Payhook)

  1. Connect Stripe at dashboard.payhook.link
  2. Stripe account setup for extension creators
  3. Monetize a browser extension without a payment backend

Claude Code prompt for payments:

Integrate Payhook into this Safari Web Extension popup and background scripts.

Requirements:
- Payhook UpgradeButton in popup for paid tiers
- Entitlement checks gate Pro features - no custom license server
- Hosted Stripe checkout via unlock.payhook.link (no card fields in the popup)
- Document any Safari-specific content security or extension page constraints

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

Next steps