Skip to content
Skillv1.0.0

browser-extension-patterns

Build browser extensions with Manifest V3 for Chrome, Firefox, and cross-browser compatibility. Covers content scripts, background workers, popup UI, storage APIs, and extension messaging. Triggers on

by organvm-iv-taxis(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from organvm-iv-taxis/a-i--skills (skills/development/browser-extension-patterns/SKILL.md). Install upstream with npx skills add organvm-iv-taxis/a-i--skills --skill browser-extension-patterns. Copyright stays with the author (MIT).

Browser Extension Patterns

Build cross-browser extensions with Manifest V3 architecture.

Manifest V3 Structure

my-extension/
├── manifest.json          # Extension manifest
├── background/
│   └── service-worker.js  # Background service worker
├── content/
│   └── content-script.js  # Injected into web pages
├── popup/
│   ├── popup.html         # Popup UI
│   ├── popup.js           # Popup logic
│   └── popup.css          # Popup styles
├── options/
│   ├── options.html       # Settings page
│   └── options.js
├── icons/
│   ├── icon-16.png
│   ├── icon-48.png
│   └── icon-128.png
└── _locales/              # Internationalization
    └── en/messages.json

Manifest Configuration

{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0.0",
  "description": "Brief description of what it does",
  "permissions": ["storage", "activeTab"],
  "host_permissions": ["https://*.example.com/*"],
  "background": {
    "service_worker": "background/service-worker.js"
  },
  "content_scripts": [{
    "matches": ["https://*.example.com/*"],
    "js": ["content/content-script.js"],
    "css": ["content/content-style.css"],
    "run_at": "document_idle"
  }],
  "action": {
    "default_popup": "popup/popup.html",
    "default_icon": {
      "16": "icons/icon-16.png",
      "48": "icons/icon-48.png",
      "128": "icons/icon-128.png"
    }
  },
  "options_page": "options/options.html",
  "icons": {
    "16": "icons/icon-16.png",
    "48": "icons/icon-48.png",
    "128": "icons/icon-128.png"
  }
}

Background Service Worker

// background/service-worker.js

// Installation
chrome.runtime.onInstalled.addListener((details) => {
  if (details.reason === 'install') {
    chrome.storage.local.set({ settings: { enabled: true, theme: 'light' } });
  }
});

// Message handling from content scripts and popup
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  switch (message.type) {
    case 'getData':
      fetchData(message.url).then(sendResponse);
      return true; // Async response
    case 'updateBadge':
      chrome.action.setBadgeText({ text: String(message.count) });
      break;
  }
});

// Alarm-based periodic tasks (replaces MV2 persistent background)
chrome.alarms.create('sync', { periodInMinutes: 30 });
chrome.alarms.onAlarm.addListener((alarm) => {
  if (alarm.name === 'sync') syncData();
});

Content Scripts

// content/content-script.js

// DOM manipulation on target pages
function enhancePage() {
  const elements = document.querySelectorAll('.target-class');
  elements.forEach(el => {
    const badge = document.createElement('span');
    badge.className = 'my-extension-badge';
    badge.textContent = 'Enhanced';
    el.appendChild(badge);
  });
}

// Run when DOM is ready
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', enhancePage);
} else {
  enhancePage();
}

// Communicate with background
async function requestData(url) {
  return chrome.runtime.sendMessage({ type: 'getData', url });
}

// Listen for messages from background/popup
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === 'getPageData') {
    sendResponse({ title: document.title, url: location.href });
  }
});

Storage Patterns

// Chrome storage API (synced across devices)
const storage = {
  async get(key) {
    const result = await chrome.storage.sync.get(key);
    return result[key];
  },

  async set(key, value) {
    await chrome.storage.sync.set({ [key]: value });
  },

  async getLocal(key) {
    const result = await chrome.storage.local.get(key);
    return result[key];
  },

  onChange(callback) {
    chrome.storage.onChanged.addListener((changes, area) => {
      callback(changes, area);
    });
  }
};

// Usage
await storage.set('settings', { theme: 'dark', enabled: true });
const settings = await storage.get('settings');

Popup UI

<!-- popup/popup.html -->
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="popup.css">
</head>
<body>
  <div id="app">
    <h2>My Extension</h2>
    <label>
      <input type="checkbox" id="enabled"> Enabled
    </label>
    <div id="status"></div>
  </div>
  <script src="popup.js"></script>
</body>
</html>
// popup/popup.js
document.addEventListener('DOMContentLoaded', async () => {
  const settings = await chrome.storage.sync.get('settings');
  document.getElementById('enabled').checked = settings.settings?.enabled;

  document.getElementById('enabled').addEventListener('change', async (e) => {
    await chrome.storage.sync.set({
      settings: { ...settings.settings, enabled: e.target.checked }
    });
    // Notify content scripts
    const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
    chrome.tabs.sendMessage(tab.id, { type: 'settingsChanged', enabled: e.target.checked });
  });
});

Cross-Browser Compatibility

// Polyfill for Firefox WebExtensions API
const browser = globalThis.browser || globalThis.chrome;

// Feature detection
const isFirefox = typeof browser !== 'undefined' && browser.runtime?.getBrowserInfo;
const isChrome = typeof chrome !== 'undefined' && chrome.runtime?.id;

Firefox Manifest Differences

{
  "background": {
    "scripts": ["background/service-worker.js"]
  },
  "browser_specific_settings": {
    "gecko": {
      "id": "my-extension@example.com",
      "strict_min_version": "109.0"
    }
  }
}

Permission Strategy

Permission When Impact
activeTab Need current tab only Low (user-triggered)
storage Need to save settings Low
tabs Need tab URLs/titles Medium
host_permissions Need page access High (shows warning)
<all_urls> Need all page access Very High (avoid if possible)

Principle: Request minimum permissions. Use activeTab over broad host permissions when possible.

Anti-Patterns

  • MV2 patterns in MV3 — No persistent background pages; use service workers and alarms
  • <all_urls> permission — Request only the hosts you need
  • Synchronous storage — Always use async chrome.storage API
  • No error handling in messaging — Messages fail silently if receiver doesn't exist
  • Heavy content scripts — Minimize injected code; communicate with background for heavy work
  • No uninstall cleanup — Use runtime.onInstalled to handle updates and cleanup

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/organvm-iv-taxis-a-i-skills-browser-extension-patterns/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

organvm-iv-taxis-a-i-skills-browser-extension-patterns.ocm.jsonjson
{
  "ocm": "1",
  "id": "organvm-iv-taxis-a-i-skills-browser-extension-patterns",
  "kind": "skill",
  "name": "browser-extension-patterns",
  "description": "Build browser extensions with Manifest V3 for Chrome, Firefox, and cross-browser compatibility. Covers content scripts, background workers, popup UI, storage APIs, and extension messaging. Triggers on browser extension development, Manifest V3, or Chrome extension requests.",
  "publisher": "organvm-iv-taxis",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "general"
    ],
    "tags": [
      "skill-md",
      "browser-extension",
      "manifest-v3",
      "chrome-extension",
      "content-scripts",
      "web-extension",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Build browser extensions with Manifest V3 for Chrome, Firefox, and cross-browser compatibility. Covers content scripts, background workers, popup UI, storage APIs, and extension messaging. Triggers on browser extension development, Manifest V3, or Chrome extension requests."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/organvm-iv-taxis/a-i--skills",
      "path": "skills/development/browser-extension-patterns/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/organvm-iv-taxis/a-i--skills/blob/HEAD/skills/development/browser-extension-patterns/SKILL.md",
      "key": "organvm-iv-taxis/a-i--skills/skills/development/browser-extension-patterns/SKILL.md"
    },
    "license": "MIT"
  },
  "instructions": "# Browser Extension Patterns\n\nBuild cross-browser extensions with Manifest V3 architecture.\n\n## Manifest V3 Structure\n\n```\nmy-extension/\n├── manifest.json          # Extension manifest\n├── background/\n│   └── service-worker.js  # Background service worker\n├── content/\n│   └── content-script.js  # Injected into web pages\n├── popup/\n│   ├── popup.html         # Popup UI\n│   ├── popup.js           # Popup logic\n│   └── popup.css          # Popup styles\n├── options/\n│   ├── options.html       # Settings page\n│   └── options.js\n├── icons/\n│   ├── icon-16.png\n│   ├── icon-48.png\n│   └── icon-128.png",
  "cost": {
    "context_tokens": 1633
  }
}

Fetch it by URL: GET /api/v1/registry/organvm-iv-taxis-a-i-skills-browser-extension-patterns/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.