chrome-extension-wxt
npx machina-cli add skill tenequm/claude-plugins/chrome-extension-wxt --openclawChrome 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
# 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
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)
// 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
// 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
// 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>
);
<!-- 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
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
// 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
// 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
// Inject script into page context
import { injectScript } from 'wxt/client';
await injectScript('/injected.js', {
keepInDom: false,
});
Building & Deployment
Production Build
# 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
# 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.
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.
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.
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.mdfor complete React setup, hooks, state management, and popular UI libraries - Chrome APIs: See
references/chrome-api.mdfor comprehensive Chrome Extension API reference with examples - Chrome 140+ Features: See
references/chrome-140-features.mdfor latest Chrome Extension APIs (sidePanel.getLayout(), etc.) - WXT API: See
references/wxt-api.mdfor complete WXT framework API documentation - Best Practices: See
references/best-practices.mdfor security, performance, and architecture patterns
Troubleshooting
Common issues and solutions:
- Module not found errors: Ensure modules are installed and properly imported
- CSP violations: Update
content_security_policyin manifest - Hot reload not working: Check browser console for errors
- Storage not persisting: Use
storage.localorstorage.synccorrectly
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.
Source
git clone https://github.com/tenequm/claude-plugins/blob/main/chrome-extension-wxt/SKILL.mdView on GitHub Overview
Chrome-extension-wxt lets you build modern, cross-browser extensions using the WXT framework with TypeScript, React, Vue, or Svelte. It enables a single codebase for Chrome, Firefox, Edge, Safari, and other Chromium-based browsers, with Manifest V3 as the standard. The skill covers project setup, structure, and common extension entry points like background, content scripts, and popup UI.
How This Skill Works
Start by creating a WXT project via npm create wxt@latest, choosing a framework template (react-ts, vue-ts, or svelte-ts). WXT uses a file-based structure (entrypoints, components, utils, public, wxt.config.ts) and auto-discovers entry points such as background.ts and content.ts. Development and packaging are driven by npm run dev, npm run build, and npm run zip, producing a store-ready extension with MV3 support.
When to Use It
- Creating a new Chrome/browser extension
- Setting up a WXT development environment for extensions
- Building extension features (popup, content scripts, background scripts)
- Implementing cross-browser compatibility with a single codebase
- Working with Manifest V3 and preparing for Chrome Web Store submission
Quick Start
- Step 1: Initialize WXT Project # 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
- Step 2: Explore Project Structure Review the generated project layout, especially entrypoints/ (background.ts, content.ts, popup.html), components/, utils/, public/icon/, and wxt.config.ts
- Step 3: Run and Build npm run dev # Start dev server with HMR npm run build # Production build npm run zip # Package for store submission
Best Practices
- Adopt Manifest V3 as the default standard and keep V2 deprecated awareness
- Organize code with the recommended entrypoints/ structure (background, content, popup, options)
- Leverage WXT’s auto-imported components and utilities to speed UI development
- Test across supported browsers using the single codebase and MV3 features
- Package and validate with npm run zip before store submission
Example Use Cases
- Developing a content-script-heavy extension that interacts with multiple sites using a single wxt.config.ts setup
- Building a popup-based productivity tool with React or Vue components integrated into the extension UI
- Creating a cross-browser utility that uses background scripts for messaging and background tasks
- Migrating an existing MV3 extension to WXT for streamlined development across browsers
- Deploying a Chrome Web Store-ready extension with a shared codebase for Chrome, Firefox, and Edge