Why this matters
Browsers still differ in key manifest areas, like background configuration and vendor metadata. Prefixed fields let you keep one sourcemanifest.json while producing browser-correct output for Chromium-family and Firefox-family targets.
How it works
Extension.js scans manifest keys and resolves prefixed entries for the selected browser. Resolution is per engine family, not per vendor:- Chromium-family targets (
chromium,chrome,edge,chromium-based, the forksbrave,opera,vivaldi,yandex, and Safari builds) resolve:chromium:,chrome:,edge: - Gecko-family targets (
firefox,gecko-based, and the forkswaterfox,librewolf) resolve:firefox:,gecko:
chromium:/firefox: keys still resolves correctly when you target a fork like brave or waterfox. An exact browser-name prefix also matches its own target (for example, brave: when you run --browser=brave).
For Chromium-based browsers (Chrome, Edge, …)
For Firefox
service_worker available only for Chromium-family outputs while keeping background.scripts for Firefox outputs.
Supported prefix map:
An exact browser-name prefix (for example,
brave:, vivaldi:, or waterfox:) additionally resolves only when you target that same browser, and wins over its family prefix (chrome: beats chromium: when targeting chrome).
Safari builds inherit the Chromium family (the converter consumes a Chrome-shaped manifest), so chromium:/chrome:/edge: keys apply to Safari too; use safari: (or webkit:) for Safari-only overrides — they take precedence over the family keys.
This works for any manifest field at any level, including permissions, content_scripts, and background.
Family-wide resolution, not per vendor
chromium:, chrome:, and edge: are interchangeable within the Chromium family: each of them applies to every Chromium-family target. Building for chrome versus chromium therefore emits an identical manifest; only the dist/<browser> folder name and the preferred launch binary differ. If you need a field for one vendor only, use its exact browser-name prefix (for example, brave:), which resolves only for that target.
When two matching prefixes set the same field, the last one in source order wins:
chrome) emits "default_title": "Second".
A matching prefixed key always overrides a plain key with the same name, regardless of where each appears in the file.
Best practices
- Keep shared defaults unprefixed: Put common fields in regular manifest keys, then prefix only browser-specific differences.
- Prefix only when behavior diverges: Use browser prefixes when runtime requirements differ.
- Build per target in continuous integration (CI): Generate and verify each browser output (
dist/<browser>) to catch compatibility regressions early. - Validate with MDN: Use MDN Web Docs to confirm support before adding browser-only settings.
Next steps
- Learn more about the Browsers available.
- Learn more about Cross-browser compatibility.

