agentsclimarketplace

Chrome ext best practices

Skill RadOrigin-LLC/RAD-Claude-Skills/plugins/rad-chrome-extension/skills/chrome-ext-best-practices

Marketplace of plugins and skills for Claude Code

Install
npx -y skills add RadOrigin-LLC/RAD-Claude-Skills --skill chrome-ext-best-practices

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

This skill should be used when working on any Chrome extension project or when the user asks about Chrome extension best practices, conventions, or patterns. Trigger when: setting up a new Chrome extension, configuring WXT, asking about MV3 architecture, "Chrome extension project structure", "WXT config", "extension entrypoints", "manifest v3 setup", "when to use content script vs service worker", "extension context boundaries", "Chrome extension build", "wxt.config.ts", "extension packaging", "Chrome Web Store submission", "cross-browser extension".

SKILL.md

5.1 KB, 995 tokens by cl100k_base, as published. Nobody here has run it

Chrome Extension Best Practices

MV3 Chrome extensions operate across multiple isolated contexts with no shared memory. The architecture must respect these boundaries while maintaining clean code organization. WXT is the recommended framework — it provides file-based routing, automatic manifest generation, and Vite-powered builds.

Core Mental Model

Every extension context (service worker, content script, popup, side panel) is a separate process. Communication happens exclusively through async message passing with JSON-serializable data. The service worker is ephemeral — it wakes to handle events and terminates after ~30 seconds of inactivity.

WXT Project Structure

my-extension/
├── src/
│   ├── entrypoints/          # Isolated contexts (file-based routing)
│   │   ├── background.ts     # Service worker
│   │   ├── popup/            # Popup UI (index.html + App.tsx)
│   │   ├── sidepanel/        # Side panel UI
│   │   ├── options/          # Options page
│   │   └── content.ts        # Content script (or *.content.ts)
│   ├── components/           # Shared React components
│   ├── hooks/                # Custom React hooks
│   ├── utils/                # Shared utilities
│   │   ├── messaging.ts      # Protocol Map definitions
│   │   └── storage.ts        # Storage wrappers
│   └── assets/               # CSS, images, SVGs
├── public/                   # Static files (copied to output)
├── wxt.config.ts             # WXT configuration
├── tsconfig.json
└── package.json

Enable srcDir: 'src' in wxt.config.ts to keep configuration files at root and source in src/.

Context Selection Guide

ContextWhen to UseLifecycleDOM AccessChrome APIs
Service WorkerEvent handling, orchestration, network interception, alarmsEphemeral (~30s idle)NoneAll
Content ScriptRead/modify web pages, inject UITied to web pageHost page DOMLimited
PopupQuick interactions, toggles, settingsTransient (dies on blur)Own documentAll
Side PanelPersistent tools, multi-step flowsPersists until closedOwn documentAll
Offscreen DocumentDOM tasks from background (DOMParser, clipboard, audio)Reason-basedOwn documentchrome.runtime only
Options PageExtension settings dashboardStandard pageOwn documentAll

Shared vs. Context-Specific Code

Shared utilities (in src/utils/ or src/shared/) — only code used by 2+ contexts:

  • TypeScript Protocol Maps for type-safe messaging
  • Storage wrappers with reactive subscription
  • Data schemas, Zod validators, API types

Context-specific code stays in its entrypoints/ file:

  • Service worker: event listeners, alarms, orchestration logic
  • Content scripts: DOM manipulation, UI injection
  • Popups/side panels: React components, UI state

Organization Principles

  • Small extensions: organize by file type (all components together)
  • Large extensions: organize by feature (group components, hooks, logic by domain)
  • Separate business logic from presentational components
  • Extension APIs (browser.*/chrome.*) must be called inside entrypoint main functions, not at module scope

WXT Entrypoints System

WXT uses file-based routing. The filename determines the entrypoint type:

  • background.ts → service worker
  • popup/index.html → popup UI
  • *.content.ts → content scripts with inline metadata via defineContentScript()
  • HTML entrypoints use <meta> tags for manifest properties

WXT automatically generates manifest.json from the directory structure and inline configurations. No manual manifest needed.

Build and Packaging

  • wxt — starts dev server with HMR
  • wxt build — production build with tree-shaking and minification
  • wxt zip — creates packaged ZIP for store submission
  • wxt build -b firefox — cross-browser targeting

Review bundles for code splitting efficiency. WXT/Vite shares large dependencies (React, Tailwind) across entrypoints. Test packed .zip locally before submission — unpacked and packed extensions behave differently.

Additional Resources

Reference Files

  • references/wxt-project-structure.md — Detailed WXT configuration, entrypoint metadata, manifest generation, and build pipeline
  • references/context-boundaries.md — Deep dive into each extension context's lifecycle, capabilities, and communication patterns

What ships with it: 2 files

9.4 KB alongside SKILL.md

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.