home / skills / tenequm / claude-plugins / chrome-extension-wxt

chrome-extension-wxt skill

/chrome-extension-wxt

This skill guides you through building cross-browser Chrome extensions with WXT, TypeScript, React, Vue, or Svelte, including MV3 setup and deployment.

npx playbooks add skill tenequm/claude-plugins --skill chrome-extension-wxt

Review the files below or copy the command above to add this skill to your agents.

Files (10)
SKILL.md
8.2 KB
---
name: chrome-extension-wxt
description: Build Chrome extensions using WXT framework with TypeScript, React, Vue, or Svelte. Use when creating browser extensions, developing cross-browser add-ons, or working with Chrome Web Store projects. Triggers on phrases like "chrome extension", "browser extension", "WXT framework", "manifest v3", or file patterns like wxt.config.ts.
---

# Chrome Extension Development with WXT

Build modern, cross-browser extensions using WXT - the next-generation framework that supports Chrome, Firefox, Edge, Safari, and all Chromium browsers with a single codebase.

## When to Use This Skill

Use this skill when:
- Creating a new Chrome/browser extension
- Setting up WXT development environment
- Building extension features (popup, content scripts, background scripts)
- Implementing cross-browser compatibility
- Working with Manifest V3 (mandatory standard as of 2025, V2 deprecated)
- Integrating React 19, Vue, Svelte, or Solid with extensions

## Quick Start Workflow

### 1. Initialize WXT Project

```bash
# Create new project with framework of choice
npm create wxt@latest

# Or with specific template
npm create wxt@latest -- --template react-ts
npm create wxt@latest -- --template vue-ts
npm create wxt@latest -- --template svelte-ts
```

### 2. Project Structure

WXT uses file-based conventions:

```
project/
├── entrypoints/              # Auto-discovered entry points
│   ├── background.ts         # Service worker
│   ├── content.ts           # Content script
│   ├── popup.html           # Popup UI
│   └── options.html         # Options page
├── components/              # Auto-imported UI components
├── utils/                   # Auto-imported utilities
├── public/                  # Static assets
│   └── icon/               # Extension icons
├── wxt.config.ts           # Configuration
└── package.json
```

### 3. Development Commands

```bash
npm run dev              # Start dev server with HMR
npm run build           # Production build
npm run zip             # Package for store submission
```

## Core Entry Points

WXT recognizes entry points by filename in `entrypoints/` directory:

### Background Script (Service Worker)

```typescript
// entrypoints/background.ts
export default defineBackground({
  type: 'module',
  persistent: false,

  main() {
    // Listen for extension events
    browser.action.onClicked.addListener((tab) => {
      console.log('Extension clicked', tab);
    });

    // Handle messages
    browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
      // Handle message
      sendResponse({ success: true });
      return true; // Keep channel open for async
    });
  },
});
```

### Content Script

```typescript
// entrypoints/content.ts
export default defineContentScript({
  matches: ['*://*.example.com/*'],
  runAt: 'document_end',

  main(ctx) {
    // Content script logic
    console.log('Content script loaded');

    // Create UI
    const ui = createShadowRootUi(ctx, {
      name: 'my-extension-ui',
      position: 'inline',
      anchor: 'body',

      onMount(container) {
        // Mount React/Vue component
        const root = ReactDOM.createRoot(container);
        root.render(<App />);
      },
    });

    ui.mount();
  },
});
```

### Popup UI

```typescript
// entrypoints/popup/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
```

```html
<!-- entrypoints/popup/index.html -->
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Extension Popup</title>
</head>
<body>
  <div id="root"></div>
  <script type="module" src="./main.tsx"></script>
</body>
</html>
```

## Configuration

### Basic wxt.config.ts

```typescript
import { defineConfig } from 'wxt';

export default defineConfig({
  // Framework integration
  modules: ['@wxt-dev/module-react'],

  // Manifest configuration
  manifest: {
    name: 'My Extension',
    description: 'Extension description',
    permissions: ['storage', 'activeTab'],
    host_permissions: ['*://example.com/*'],
  },

  // Browser target
  browser: 'chrome', // or 'firefox', 'edge', 'safari'
});
```

## Common Patterns

### Type-Safe Storage

```typescript
// utils/storage.ts
import { storage } from 'wxt/storage';

export const storageHelper = {
  async get<T>(key: string): Promise<T | null> {
    return await storage.getItem<T>(`local:${key}`);
  },

  async set<T>(key: string, value: T): Promise<void> {
    await storage.setItem(`local:${key}`, value);
  },

  watch<T>(key: string, callback: (newValue: T | null) => void) {
    return storage.watch<T>(`local:${key}`, callback);
  },
};
```

### Type-Safe Messaging

```typescript
// utils/messaging.ts
interface Messages {
  'get-data': {
    request: { key: string };
    response: { value: any };
  };
}

export async function sendMessage<K extends keyof Messages>(
  type: K,
  payload: Messages[K]['request']
): Promise<Messages[K]['response']> {
  return await browser.runtime.sendMessage({ type, payload });
}
```

### Script Injection

```typescript
// Inject script into page context
import { injectScript } from 'wxt/client';

await injectScript('/injected.js', {
  keepInDom: false,
});
```

## Building & Deployment

### Production Build

```bash
# Build for specific browser
npm run build -- --browser=chrome
npm run build -- --browser=firefox

# Create store-ready ZIP
npm run zip
npm run zip -- --browser=firefox
```

### Multi-Browser Build

```bash
# Build for all browsers
npm run zip:all
```

Output: `.output/my-extension-{version}-{browser}.zip`

## Modern Stacks (2025)

Popular technology combinations for building Chrome extensions:

### WXT + React + Tailwind + shadcn/ui
Most popular stack in 2025. Combines utility-first styling with pre-built accessible components.

```bash
npm create wxt@latest -- --template react-ts
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
npx shadcn@latest init
```

**Best for:** Modern UIs with consistent design system
**Example:** https://github.com/imtiger/wxt-react-shadcn-tailwindcss-chrome-extension

### WXT + React + Mantine UI
Complete component library with 100+ components and built-in dark mode.

```bash
npm create wxt@latest -- --template react-ts
npm install @mantine/core @mantine/hooks
```

**Best for:** Feature-rich extensions needing complex components
**Example:** https://github.com/ongkay/WXT-Mantine-Tailwind-Browser-Extension

### WXT + React + TypeScript (Minimal)
Clean setup for custom designs without UI library dependencies.

```bash
npm create wxt@latest -- --template react-ts
```

**Best for:** Simple extensions or highly custom designs

## Advanced Topics

For detailed information on advanced topics, see the reference files:

- **React Integration**: See `references/react-integration.md` for complete React setup, hooks, state management, and popular UI libraries
- **Chrome APIs**: See `references/chrome-api.md` for comprehensive Chrome Extension API reference with examples
- **Chrome 140+ Features**: See `references/chrome-140-features.md` for latest Chrome Extension APIs (sidePanel.getLayout(), etc.)
- **WXT API**: See `references/wxt-api.md` for complete WXT framework API documentation
- **Best Practices**: See `references/best-practices.md` for security, performance, and architecture patterns

## Troubleshooting

Common issues and solutions:

1. **Module not found errors**: Ensure modules are installed and properly imported
2. **CSP violations**: Update `content_security_policy` in manifest
3. **Hot reload not working**: Check browser console for errors
4. **Storage not persisting**: Use `storage.local` or `storage.sync` correctly

For detailed troubleshooting, see `references/troubleshooting.md`

## Resources

### Official Documentation
- WXT Docs: https://wxt.dev
- Chrome Extension Docs: https://developer.chrome.com/docs/extensions
- Firefox Extension Docs: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons

### Bundled Resources

- **scripts/**: Helper utilities for common extension tasks
- **references/**: Detailed documentation for advanced features
- **assets/**: Starter templates and example components

Use these resources as needed when building your extension.

Overview

This skill helps you build modern Chrome and cross-browser extensions using the WXT framework with TypeScript and your choice of React, Vue, Svelte, or Solid. It provides practical guidance on project structure, entry points (background, content, popup), manifest v3 configuration, and build/deploy workflows. Use it to speed up development, ensure multi-browser compatibility, and produce store-ready ZIP packages.

How this skill works

The skill inspects typical WXT project files such as wxt.config.ts, entrypoints/*, and package.json patterns and recognizes triggers like "chrome extension", "browser extension", "WXT framework", and Manifest V3 mentions. It outlines how WXT auto-discovers entry points, integrates UI frameworks, manages type-safe storage and messaging, and invokes build commands for dev, production, and multi-browser packaging. It also highlights common patterns for script injection, service worker background scripts, content scripts, and popup UI wiring.

When to use it

  • Starting a new Chrome or cross-browser extension project with TypeScript and modern UI frameworks
  • Setting up a WXT development environment and project scaffolding
  • Implementing background service workers, content scripts, popups, or options pages
  • Targeting Manifest V3 and preparing store-ready ZIP builds
  • Migrating or adapting extensions for multi-browser support (Chrome, Firefox, Edge, Safari)

Best practices

  • Organize code under entrypoints/, components/, utils/, and public/ following WXT conventions
  • Use type-safe storage and messaging helpers to reduce runtime errors and enable IDE support
  • Keep background logic in service workers and prefer non-persistent modules per MV3 requirements
  • Define explicit host_permissions and minimal permissions in wxt.config.ts to follow least privilege
  • Use framework-specific modules (e.g., @wxt-dev/module-react) and enable HMR for fast iteration

Example use cases

  • Create a React + TypeScript popup extension using WXT and Tailwind for a polished UI
  • Build a content-script feature that injects a shadow-root React app on matched sites
  • Package a single codebase for Chrome and Firefox with browser-specific manifest adjustments
  • Implement type-safe runtime messaging between content scripts and the background service worker
  • Produce store-ready ZIPs and automate builds for multiple browser targets

FAQ

Does WXT support Manifest V3?

Yes. WXT is designed for Manifest V3 and provides conventions for service workers, content scripts, and CSP handling required by modern stores.

Can I use React or Vue with WXT?

Yes. WXT supports React, Vue, Svelte and other frameworks via modules and templates (e.g., react-ts, vue-ts) for seamless integration.

How do I build for multiple browsers?

Use WXT build commands with the --browser flag or run provided zip:all scripts to create browser-specific ZIP packages.