Browser extensions: build, session handoff, packaging, stores
Read references/BROWSER-EXTENSIONS.md before applying any of this.
That file is the standard; everything below it is a summary to help you decide
whether this skill applies and to check your work afterwards.
What this standard covers
- Cross-browser baseline
- Session handoff
- Isolated worlds and the service worker
- Per-site adapters
- Packaging: one source, N environments
- Store submission
- Distributing builds yourself
- Mobile: there is no mobile extension
Failure modes
| Symptom | Cause |
|---|---|
| Session handoff works in Chrome, silently fails in Firefox | No content-script fallback; Firefox lacks externally_connectable |
| Token expiry nonsense after idle | Stored relative expiresIn instead of an absolute timestamp |
| Page never sees the extension's result | Isolated-world write to window; use DOM dataset + re-fired CustomEvent |
First message after idle returns undefined |
Service worker asleep; retry with delay |
| Extension works for the dev, not for users | Production zip carries dev config, or store build points at localhost hosts |
| Reviewer rejects over permissions | Localhost entries left in host_permissions, or broad permissions without written justification |
| Published extension's API calls fail | Extension id never added to backend CORS allowlist |
| One site's integration silently breaks | Third-party DOM changed; no selector fallback, no manual smoke pass |
| "Which version are you on?" unanswerable | No version echo header on the distribution endpoint |
Checklist
- API shim at the top of every script; one manifest with the
geckoblock - Both handoff paths (external message + content-script fallback); payload validated; absolute expiry in
storage.local - Runtime sender-origin allowlist redundant with the manifest
- Isolated-world signaling via DOM dataset + re-fired CustomEvent; service-worker wake-up retry
- Site integrations as adapter tables with ordered selector fallbacks
- CI writes config + patches manifest (hosts, version from tag); localhost-permission removal decided and recorded
- Store assets/policy prepared to spec; privacy policy covers extension data; permissions justified in writing
- Post-approval loop: extension id → store URL variable → backend CORS allowlist
- Publication automated from CI
- Self-distribution: semver blobs, channel ladder, PR-label pinning, version echo header, empty-zip degradation
- Mobile requests answered with a feasibility study, not a mobile extension
Generated from docs/guides/BROWSER-EXTENSIONS.md by scripts/build-marketplace.mjs. Do not edit this file: change the source document, or its entry in catalog/marketplace.catalog.json, and re-run the generator.