B

Browser Extension Builder Toolkit

Enterprise-grade skill for expert, building, browser, extensions. Includes structured workflows, validation checks, and reusable patterns for utilities.

SkillClipticsutilitiesv1.0.0MIT
0 views0 copies

Browser Extension Builder

A browser extension development skill for building Chrome, Firefox, and cross-browser extensions with manifest v3, content scripts, background workers, and popup interfaces.

When to Use

Choose Browser Extension Builder when:

  • Creating Chrome or Firefox extensions with manifest v3
  • Building content scripts that modify web pages or extract data
  • Developing popup UIs, options pages, and background service workers
  • Porting extensions between Chrome and Firefox with cross-browser compatibility

Consider alternatives when:

  • Building a full web application — deploy as a standard web app
  • Needing server-side processing — build a web service with a simple browser bookmarklet
  • Creating a simple page script — use a userscript manager like Tampermonkey

Quick Start

# Project structure for a Chrome extension mkdir -p my-extension/{src,public,dist}
// manifest.json (Manifest V3) { "manifest_version": 3, "name": "My Extension", "version": "1.0.0", "description": "A useful browser extension", "permissions": ["storage", "activeTab", "scripting"], "action": { "default_popup": "popup.html", "default_icon": { "16": "icons/icon-16.png", "48": "icons/icon-48.png", "128": "icons/icon-128.png" } }, "background": { "service_worker": "background.js", "type": "module" }, "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"], "css": ["content.css"], "run_at": "document_idle" } ], "options_page": "options.html" }
// background.ts - Service worker chrome.runtime.onInstalled.addListener(({ reason }) => { if (reason === 'install') { chrome.storage.local.set({ settings: { enabled: true, theme: 'auto' } }); } }); chrome.action.onClicked.addListener(async (tab) => { if (!tab.id) return; await chrome.scripting.executeScript({ target: { tabId: tab.id }, func: () => { document.body.classList.toggle('extension-active'); } }); }); // Message handling between components chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.type === 'GET_DATA') { fetchData(message.url).then(sendResponse); return true; // Keep channel open for async response } }); async function fetchData(url: string) { const response = await fetch(url); return response.json(); } // content.ts - Content script function injectUI() { const container = document.createElement('div'); container.id = 'my-extension-root'; container.style.cssText = 'position:fixed;top:10px;right:10px;z-index:99999;'; document.body.appendChild(container); // Send message to background chrome.runtime.sendMessage( { type: 'GET_DATA', url: window.location.href }, (response) => { container.innerHTML = `<div class="ext-widget">${response.title}</div>`; } ); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', injectUI); } else { injectUI(); }

Core Concepts

Extension Architecture

ComponentFileRoleAccess
Service Workerbackground.jsEvent handling, API callsChrome APIs, no DOM
Content Scriptcontent.jsPage DOM modificationPage DOM, limited Chrome APIs
Popuppopup.html/jsUser interface (action click)Chrome APIs, own DOM
Options Pageoptions.html/jsExtension settingsChrome APIs, own DOM
DevTools Paneldevtools.html/jsDeveloper tools integrationInspected page, Chrome APIs
Side Panelsidepanel.html/jsPersistent side panelChrome APIs, own DOM

Cross-Browser Compatibility

// browser-polyfill wrapper for Chrome/Firefox compatibility const browserAPI = typeof browser !== 'undefined' ? browser : chrome; // Storage abstraction async function getStorage(keys: string[]): Promise<Record<string, any>> { return new Promise((resolve) => { browserAPI.storage.local.get(keys, resolve); }); } async function setStorage(data: Record<string, any>): Promise<void> { return new Promise((resolve) => { browserAPI.storage.local.set(data, resolve); }); } // Tab query abstraction async function getActiveTab() { const tabs = await browserAPI.tabs.query({ active: true, currentWindow: true }); return tabs[0]; }

Configuration

OptionDescriptionDefault
manifest_versionManifest version (v2 deprecated, use v3)3
target_browsersTarget browsers: chrome, firefox, both"chrome"
content_script_matchesURL patterns for content script injection["<all_urls>"]
permissionsRequired browser permissions["storage","activeTab"]
build_toolBundler: webpack, vite, rollup"vite"
frameworkUI framework: react, vue, svelte, vanilla"react"
hot_reloadEnable hot reload during developmenttrue
source_mapsGenerate source maps for debuggingtrue

Best Practices

  1. Request minimal permissions and use activeTab instead of broad host permissions whenever possible — users are more likely to install extensions that request fewer permissions, and Chrome Web Store reviews are faster
  2. Use Chrome's storage.local API instead of localStorage in service workers because service workers do not have access to localStorage and the storage API provides better cross-component access
  3. Handle service worker lifecycle properly since manifest v3 service workers can be terminated at any time; do not store state in global variables, use chrome.storage for persistence, and re-register listeners on each service worker startup
  4. Isolate content script styles using Shadow DOM or highly specific CSS selectors to prevent your extension's styles from affecting the host page and vice versa
  5. Test with the built-in Chrome extension debugger by loading your extension unpacked, using the service worker inspector for background script debugging, and the page inspector for content scripts

Common Issues

Service worker becoming inactive: Manifest v3 service workers are terminated after 30 seconds of inactivity, losing all in-memory state. Store important data in chrome.storage, use chrome.alarms for periodic tasks instead of setInterval, and re-initialize listeners at the top level of your service worker script.

Content script CSP conflicts: Some websites have strict Content Security Policies that block inline scripts and styles injected by extensions. Use the scripting API with executeScript instead of inline event handlers, load CSS from extension files rather than injecting inline styles, and use the world: 'MAIN' option when you need to access the page's JavaScript context.

Cross-origin requests blocked in content scripts: Content scripts inherit the page's CORS restrictions. Make cross-origin API calls from the service worker using chrome.runtime.sendMessage to relay requests, or declare host permissions in the manifest for specific domains you need to access.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates