From supervibe
Use WHEN setting up or modifying the build pipeline for a Chrome MV3 extension to choose bundler (Vite-CRXJS / WXT / Plasmo / vanilla), wire HMR for popup, generate icons, lint manifest, and produce a CWS-ready zip. Triggers: 'настрой сборку расширения', 'сделай build для chrome extension', 'добавь HMR в popup', 'упакуй для CWS', 'web-ext lint'.
npx claudepluginhub vtrka/supervibe --plugin supervibeThis skill is limited to using the following tools:
Set up or fix the build / lint / package pipeline for a Chrome MV3 extension. Outcome: `npm run build` produces a CWS-ready `dist/` (or `web-ext-artifacts/*.zip`) that passes `web-ext lint` with zero warnings.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
Set up or fix the build / lint / package pipeline for a Chrome MV3 extension. Outcome: npm run build produces a CWS-ready dist/ (or web-ext-artifacts/*.zip) that passes web-ext lint with zero warnings.
chrome-extension-architect has approved the manifest design.web-ext lint warning blocks merge and you need to chase it to root cause.NOT for:
chrome-extension-architect.chrome-extension-developer.creative-director + ux-ui-designer.Follow docs/references/skill-expert-operating-standard.md: start from source of truth, preserve retrieval evidence, apply scope safety, use real producers with runtime receipts for durable delegated outputs, verify before completion claims, and keep confidence below gate when evidence is partial.
manifest.json (or manifest.json.tpl if generated). If absent → STOP and tell the user to run chrome-extension-architect first.package.json for current scripts + devDependencies (which bundler is wired, if any)..supervibe/memory/decisions/ for any past bundler PRD decision section. If one exists, the choice is locked unless an explicit re-evaluation PRD decision section is written.vite.config.* / wxt.config.* / plasmo.config.* if present.| Situation | Pick | Why |
|---|---|---|
| TypeScript + React/Vue/Svelte popup, want HMR for popup, hate magic | Vite + @crxjs/vite-plugin | Most explicit. You write manifest.json by hand, the plugin wires HMR + entry-points |
Want zero-config, conventional file layout (entrypoints/), opinions are fine | WXT | Auto-imports, type-safe messaging helpers, generated manifest. Cost: less explicit |
| React-heavy team, want Next.js-like file-based routing for popup/options | Plasmo | Tightest React DX. Cost: heaviest framework, more abstraction over manifest |
| Pure vanilla JS, no bundler, fast iteration | No bundler — copy extension/ directly | Minimal moving parts. Fine for ≤5 files. Loses TS, HMR, tree-shaking |
When changing bundler on an existing project, write the migration PRD decision section FIRST. Document the pain point being solved.
Confirm bundler choice. If a .supervibe/memory/decisions/<date>-extension-bundler.md PRD decision section exists, follow it. Otherwise propose one with the decision tree above and wait for user "yes".
Install bundler + tooling.
# Vite + CRXJS path:
npm i -D vite @crxjs/vite-plugin @types/chrome typescript
Other paths analogous — install per chosen bundler's docs (verify versions via supervibe:mcp-discovery → context7 if available).
Wire vite.config.ts (CRXJS path):
import { defineConfig } from 'vite';
import { crx } from '@crxjs/vite-plugin';
import manifest from './extension/manifest.json' assert { type: 'json' };
export default defineConfig({
plugins: [crx({ manifest })],
build: { outDir: 'dist', emptyOutDir: true, sourcemap: true },
});
Add npm scripts to package.json (mirror stack-packs/chrome-extension-mv3/configs/package.json.tpl):
dev — watch modebuild — production build + web-ext lintlint — eslint + web-ext linttypecheck — tsc --noEmittest — vitestpackage — zip dist/ for CWSGenerate or place icons. extension/public/icons/icon-{16,32,48,128}.png. If missing, ask user for source 512x512.png and use a tool (sharp/imagemagick) to downsample. Do NOT ship placeholder icons to CWS — automatic rejection.
Set up _locales/en/messages.json with at minimum extName + extDescription keys (referenced by __MSG_*__ in manifest):
{
"extName": { "message": "<extension display name>" },
"extDescription": { "message": "<short description, ≤132 chars>" }
}
Write the package validator (scripts/package-cws.mjs) that:
dist/manifest.json, asserts manifest_version === 3host_permissions entry has tightest possible match-patterneval(, new Function(, setTimeout(.*string, fails on hits_locales/en/messages.json exists with required keyssharp or read first bytes for PNG signature)dist/ to web-ext-artifacts/<name>-<version>.zipWire web-ext lint (scripts/web-ext-lint.mjs) — runs npx web-ext lint --source-dir=dist --warnings-as-errors. Fails the build on any warning.
Smoke test load-unpacked: print to user Open chrome://extensions → enable Developer mode → Load unpacked → select dist/. Optionally use Playwright MCP if available for automated load + console-error scrape.
Score the resulting pipeline against confidence-rubrics/scaffold.yaml. Required: ≥9.
Returns:
package.json scripts (dev / build / lint / typecheck / test / package)scripts/web-ext-lint.mjs and scripts/package-cws.mjs_locales/en/messages.json skeletonnpm run build && npm run lint exits 0=== Chrome Extension Build Pipeline ===
Bundler: <choice> PRD decision section: <path or "ad-hoc — recommend writing one">
Scripts wired: dev / build / lint / typecheck / test / package
Build output: dist/ (size: <KB>)
web-ext lint: <warnings count> (must be 0 to ship)
CWS package: web-ext-artifacts/<name>-<version>.zip (<KB>)
Confidence: <N>.<dd>/10
Override: <true|false>
Rubric: scaffold
web-ext lint --warnings-as-errors. CWS catches the same warnings on upload and rejects with worse error messages.script-src 'self' is non-negotiable for trust score.unsafe-eval or unsafe-inline to CSP. If a third-party script must run, isolate via sandbox.pages instead.After running:
npm run build exits 0npm run lint exits 0 (eslint + web-ext lint zero warnings)npm run typecheck exits 0 if TypeScriptnpm run package produces a valid zip in web-ext-artifacts/dist/ as unpacked extension shows zero console errors in DevTools (popup + service worker + content scripts)chrome://extensions does not flag any "Errors" badge for the unpacked loadagents/stacks/chrome-extension/chrome-extension-architect.md — owns the manifest and permissions strategyagents/stacks/chrome-extension/chrome-extension-developer.md — implements features on top of this build pipelinesupervibe:mcp-discovery — fetch current docs for chosen bundlerconfidence-rubrics/scaffold.yaml — the scoring rubric for this outputstack-packs/chrome-extension-mv3/manifest.yaml — full project scaffold including this skill