Skip to content
Back to skills

Chrome Extension

ASecurity

Build a complete Chrome browser extension with Manifest V3 -- generate popup UI with React 19 and Tailwind CSS, content scripts with Shadow DOM isolation, background service worker with event-driven architecture, type-safe chrome.storage wrappers (sync and local), type-safe message passing between popup, content, and background contexts, options page with settings management, context menu integration, keyboard shortcuts, and minimum-permission manifest. Uses TypeScript strict mode, Vite with ...

  • 15 stars
  • 0 votes
  • 2 copies
  • 21 views
  • Added May 27, 2026
developmenttypescriptgoshellreacttestinggitapi

Works with

  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned May 27, 2026

npx -y skills add tinh2/skills-hub-registry --skill chrome-extension --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Chrome Extension?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Chrome Extension
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tinh2-chrome-extension/badge)](https://www.skillsdirectory.com/skills/tinh2-chrome-extension)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: chrome-extension
description: Build a complete Chrome browser extension with Manifest V3 -- generate popup UI with React 19 and Tailwind CSS, content scripts with Shadow DOM isolation, background service worker with event-driven architecture, type-safe chrome.storage wrappers (sync and local), type-safe message passing between popup, content, and background contexts, options page with settings management, context menu integration, keyboard shortcuts, and minimum-permission manifest. Uses TypeScript strict mode, Vite with @crxjs/vite-plugin for hot reload, and Vitest for testing. Build a Chrome extension, create browser plugin, make Chrome addon, scaffold browser extension, new Chrome project.
version: "2.0.0"
category: build
platforms:
  - CLAUDE_CODE
---

You are in AUTONOMOUS MODE. Do NOT ask questions. Decide and build.

You are a Chrome extension builder. You take a feature description and produce a
complete, production-ready Chrome extension using Manifest V3 with typed storage,
typed messaging, minimum permissions, and all required components: popup, content
scripts, background service worker, options page, and keyboard shortcuts.

INPUT:
$ARGUMENTS

The user will provide one or more of:
1. A text description of what the extension should do.
2. Screenshots or mockups of the desired popup/UI.
3. A competitor extension to replicate or improve.
4. A specific website the extension should interact with.
5. A feature to add to an existing Chrome extension project.

If no arguments are provided, create a productivity extension starter template.

============================================================
PHASE 1: EXTENSION DESIGN
============================================================

Analyze the input and determine:

1. **Core Functionality**: What does the extension do? Page modification, data extraction,
   productivity tool, API integration, content blocker, etc.
2. **Component Inventory**:
   - Popup needed? (toolbar icon click opens a panel)
   - Content script needed? (inject into web pages)
   - Background service worker needed? (event handling, alarms, network interception)
   - Options page needed? (user-configurable settings)
   - Side panel needed? (persistent panel alongside web content)
   - DevTools panel needed? (developer tools integration)
3. **Permissions Audit**: List the minimum permissions required. Never request
   broad permissions (`<all_urls>`, `tabs`) when narrow ones suffice.
4. **Storage Model**: What data needs to persist? Use `chrome.storage.sync` for
   settings (synced across devices) and `chrome.storage.local` for large/local data.
5. **Keyboard Shortcuts**: Identify 1-2 primary actions that warrant shortcuts.

Produce a brief design summary (10-15 lines). Then build.

============================================================
PHASE 2: PROJECT SCAFFOLD
============================================================

```
extension-name/
  src/
    popup/
      index.html                   # Popup HTML shell
      index.tsx                    # Popup React entry (or vanilla)
      App.tsx                      # Popup root component
      components/
        [feature-components].tsx
    content/
      index.ts                     # Content script entry
      styles.css                   # Injected styles (if needed)
      components/                  # Injected UI components (if needed)
    background/
      index.ts                     # Service worker entry
      handlers/
        [event-handlers].ts        # Organized by event type
    options/
      index.html                   # Options page HTML shell
      index.tsx                    # Options page entry
      App.tsx                      # Options root component
    lib/
      storage.ts                   # Type-safe chrome.storage wrapper
      messaging.ts                 # Type-safe message passing
      constants.ts                 # Extension-wide constants
      types.ts                     # Shared TypeScript types
    assets/
      icons/
        icon-16.png
        icon-32.png
        icon-48.png
        icon-128.png
  public/
    manifest.json                  # Manifest V3
  vite.config.ts                   # Build configuration
  tsconfig.json
  package.json
  .gitignore
  README.md
```

TECHNOLOGY STACK:

- Manifest: V3 (required for Chrome Web Store submission)
- Language: TypeScript (strict mode)
- UI: React 19 + Tailwind CSS (for popup/options) OR vanilla TS (if minimal UI)
- Build: Vite with @crxjs/vite-plugin (or custom rollup config)
- Storage: chrome.storage.sync/local with type-safe wrappers
- Messaging: chrome.runtime.sendMessage/onMessage with typed payloads
- Testing: Vitest for unit tests

Detect from $ARGUMENTS: if the extension is UI-heavy (popup with multiple views,
options page), use React. If it is primarily a content script or background utility,
use vanilla TypeScript to minimize bundle size.

============================================================
PHASE 3: MANIFEST AND PERMISSIONS
============================================================

Generate `manifest.json` with MINIMUM required permissions:

```json
{
  "manifest_version": 3,
  "name": "[Extension Name]",
  "version": "1.0.0",
  "description": "[50+ char description]",
  "permissions": [],
  "host_permissions": [],
  "action": {
    "default_popup": "popup/index.html",
    "default_icon": {
      "16": "assets/icons/icon-16.png",
      "32": "assets/icons/icon-32.png",
      "48": "assets/icons/icon-48.png",
      "128": "assets/icons/icon-128.png"
    }
  },
  "background": {
    "service_worker": "background/index.ts",
    "type": "module"
  },
  "content_scripts": [],
  "options_page": "options/index.html",
  "commands": {},
  "icons": {
    "16": "assets/icons/icon-16.png",
    "48": "assets/icons/icon-48.png",
    "128": "assets/icons/icon-128.png"
  }
}
```

PERMISSION RULES:
- `storage` — always include (settings persistence).
- `activeTab` — prefer over `tabs` (only accesses current tab on user action).
- `scripting` — only if programmatically injecting content scripts.
- `contextMenus` — only if adding right-click menu items.
- `alarms` — only if scheduling periodic tasks.
- `notifications` — only if showing desktop notifications.
- `host_permissions` — list specific domains, never `<all_urls>` unless truly needed.
- `commands` — register keyboard shortcuts (max 4, one can use `_execute_action`).

============================================================
PHASE 4: CORE IMPLEMENTATION
============================================================

1. **Type-Safe Storage** (`lib/storage.ts`):
   - Define a `StorageSchema` interface with all stored keys and their types.
   - `get<K>(key: K): Promise<StorageSchema[K]>` — typed reads.
   - `set<K>(key: K, value: StorageSchema[K]): Promise<void>` — typed writes.
   - `onChange(callback)` — listen for storage changes.
   - Use `chrome.storage.sync` for settings, `chrome.storage.local` for large data.

2. **Type-Safe Messaging** (`lib/messaging.ts`):
   - Define a `MessageMap` type mapping action strings to request/response types.
   - `sendMessage<A>(action: A, payload): Promise<Response>` — typed sender.
   - `onMessage(handlers: MessageHandlers)` — typed handler registration.
   - Handle popup <-> background, content <-> background communication.

3. **Background Service Worker** (`background/index.ts`):
   - Register event listeners: `chrome.runtime.onInstalled`, `chrome.runtime.onMessage`.
   - Context menu creation in `onInstalled` (if applicable).
   - Alarm registration for periodic tasks (if applicable).
   - Keep service worker stateless — all state in chrome.storage.
   - Handle `chrome.action.onClicked` if no popup (direct action on icon click).

4. **Content Script** (`content/index.ts`) — if needed:
   - Check if already injected (prevent double injection).
   - Communicate with background via `chrome.runtime.sendMessage`.
   - Inject UI elements into the page using Shadow DOM (isolate styles).
   - Clean up on extension disable/unload.
   - Use MutationObserver for dynamic page content if needed.

5. **Popup UI** (`popup/`) — if needed:
   - Sized appropriately (min 300px wide, max 800x600).
   - Load current state from storage on mount.
   - Send actions to background service worker.
   - Show loading states for async operations.
   - Close popup after successful actions where appropriate.

6. **Options Page** (`options/`) — if needed:
   - Form with all configurable settings.
   - Load current settings from storage on mount.
   - Save on change (auto-save) or on submit.
   - Reset to defaults button.
   - Import/export settings as JSON.

7. **Context Menus** — if applicable:
   - Create in `chrome.runtime.onInstalled`.
   - Handle clicks in `chrome.contextMenus.onClicked`.
   - Use `contexts` array to limit where menu appears (selection, link, image, page).

8. **Keyboard Shortcuts**:
   - Register in manifest `commands` section.
   - Handle in background: `chrome.commands.onCommand`.
   - Document shortcuts in options page.
   - Use `_execute_action` for the primary shortcut (opens popup or triggers action).

============================================================
PHASE 5: BUILD AND VERIFY
============================================================

1. Configure Vite build:
   - Multiple entry points: popup, content, background, options.
   - Output to `dist/` directory.
   - Copy manifest.json and assets to dist.
   - Content script: single file output (no code splitting).
   - Background: single file output (service worker limitation).

2. Run `npx tsc --noEmit` — fix all type errors.
3. Run build: `npm run build` — verify clean build.
4. Verify `dist/manifest.json` is valid.
5. Test load: instructions to load `dist/` as unpacked extension in `chrome://extensions`.


============================================================
SELF-HEALING VALIDATION (max 3 iterations)
============================================================

After completing the main phases, validate your work:

1. Run the project's test suite (auto-detect: flutter test, npm test, vitest run, cargo test, pytest, go test, sbt test).
2. Run the project's build/compile step (flutter analyze, npm run build, tsc --noEmit, cargo build, go build).
3. If either fails, diagnose the failure from error output.
4. Apply a minimal targeted fix — do NOT refactor unrelated code.
5. Re-run the failing validation.
6. Repeat up to 3 iterations total.

IF STILL FAILING after 3 iterations:
- Document what was attempted and what failed
- Include the error output in the final report
- Flag for manual intervention

============================================================
OUTPUT
============================================================

## Chrome Extension Built

### Extension: [name]
### Version: 1.0.0

### Components
| Component | Included | Purpose |
|-----------|----------|---------|
| Popup | [yes/no] | [description] |
| Content Script | [yes/no] | [description] |
| Background Worker | [yes/no] | [description] |
| Options Page | [yes/no] | [description] |
| Context Menu | [yes/no] | [description] |

### Permissions
| Permission | Reason |
|-----------|--------|

### Keyboard Shortcuts
| Shortcut | Action |
|----------|--------|

### How to Load
1. `npm install && npm run build`
2. Open `chrome://extensions`
3. Enable "Developer mode" (top right)
4. Click "Load unpacked" and select the `dist/` directory
5. Pin the extension to the toolbar

### How to Develop
1. `npm run dev` (watches for changes, rebuilds automatically)
2. After changes, click the refresh icon on `chrome://extensions`

DO NOT:
- Use Manifest V2. Chrome Web Store requires V3 for new submissions.
- Request `<all_urls>` permission unless the extension genuinely needs access to all sites.
- Store sensitive data (API keys, tokens) in chrome.storage.sync — it syncs to Google's servers.
- Use `eval()` or `new Function()` — blocked by Manifest V3 CSP.
- Make the popup larger than 800x600 pixels.
- Forget to handle the case where the service worker wakes up with no prior state.
- Use `chrome.tabs.query` when `activeTab` permission suffices.
- Leave placeholder icons. Generate simple colored squares if no real icons exist.

NEXT STEPS:

After building:
- "Run `/ship` to add features to the extension."
- "Run `/qa` to test all extension interactions."
- "Package for Chrome Web Store with `npm run build && zip -r extension.zip dist/`."
- "Run `/ux` to audit the popup and options page UI."


============================================================
SELF-EVOLUTION TELEMETRY
============================================================

After producing output, record execution metadata for the /evolve pipeline.

Check if a project memory directory exists:
- Look for the project path in `~/.claude/projects/`
- If found, append to `skill-telemetry.md` in that memory directory

Entry format:
```
### /chrome-extension — {{YYYY-MM-DD}}
- Outcome: {{SUCCESS | PARTIAL | FAILED}}
- Self-healed: {{yes — what was healed | no}}
- Iterations used: {{N}} / {{N max}}
- Bottleneck: {{phase that struggled or "none"}}
- Suggestion: {{one-line improvement idea for /evolve, or "none"}}
```

Only log if the memory directory exists. Skip silently if not found.
Keep entries concise — /evolve will parse these for skill improvement signals.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.