dist/<browser>.
How it works
Path resolution runs in two places:- Manifest compilation pipeline: resolves manifest-declared paths to emitted assets.
- Path-resolve plugin for JS/TS: rewrites static path literals passed to supported extension APIs (for example,
runtime.getURL,tabs.update,scripting.*,action.*,sidePanel.*).
Supported input styles
Extension.js normalizes common path inputs as follows:| Input style | Example | Normalized output |
|---|---|---|
| Public root (absolute) | /public/icons/icon.png | icons/icon.png |
| Public root (relative) | public/icons/icon.png, ./public/icons/icon.png | icons/icon.png |
| Root absolute | /foo/bar.js | foo/bar.js |
| Root special folder | /pages/popup.njk | pages/popup.html |
| Special folders | pages/popup.html, scripts/content.tsx | pages/popup.html, scripts/content.js |
| Parent-relative from author file | ../scripts/content.ts | scripts/content.js (when resolving to project root special folder) |
pages/ and scripts/ includes:
.ts,.tsx,.js,.jsx→.js.njk,.nunjucks,.html→.html.scss,.sass,.less,.css→.css
Cases Extension.js does not rewrite
To avoid false positives, Extension.js intentionally skips these inputs:http://andhttps://URLsdata:URLschrome://URLsmoz-extension://URLs- Glob patterns (
*,?,{},[]) - Non-static/dynamic expressions that the build cannot safely resolve
Manifest output examples
Assuming target browserchrome:
| Manifest field | Input path | Output path |
|---|---|---|
action.default_popup | /src/popup.html | action/index.html |
background.page | /src/background.html | background/index.html |
background.service_worker | /src/background.ts | background/service_worker.js |
browser_action.default_popup | /src/popup.html | action/index.html |
chrome_url_overrides.newtab | /src/newtab.html | newtab/index.html |
content_scripts.js | /src/content_script.ts | content_scripts/content-0.js |
content_scripts.css | /src/content_style.css | content_scripts/content-0.css |
devtools_page | /src/devtools.html | devtools/index.html |
options_ui.page | /src/options.html | options/index.html |
sandbox.pages | /src/sandbox.html | sandbox/page-0.html |
side_panel.default_path | /src/sidepanel.html | sidebar/index.html |
sidebar_action.default_panel | /src/sidebar_panel.html | sidebar/index.html |
storage.managed_schema | /src/storage_schema.json | storage/managed_schema.json |
user_scripts.api_script | /src/user_script.ts | user_scripts/api_script.js |
dist/<browser>.
Referencing output files
For browser APIs likechrome.runtime.getURL(), prefer stable, output-root paths:
chrome-extension:<extension-id>/icons/icon.png
Diagnostics and safety checks
The resolver warns you when it cannot resolve a referenced path to a packaged asset (for example, nestedsrc/pages/... or missing public/ files after rewrite).Extension.js de-duplicates warnings per file transform pass to reduce noise.
Important path rules
- Leading
/means extension output root, not filesystem root. public/...and/public/...normalize to output-root assets.pages/andscripts/are special folders with extension mapping rules.- Extension.js preserves absolute OS file paths instead of treating them as extension output paths.
- Extension.js skips dynamic expressions when it cannot safely determine the final packaged path.
Best practices
- Keep
pages/,scripts/, andpublic/at project root for predictable rewrites. - Use static literals for extension API paths when possible; Extension.js may skip dynamic expressions.
- Treat
/public/...as output-root assets and avoid source-relative assumptions at runtime. - Validate warnings during
devas they usually indicate path mismatches before packaging.
Next steps
- Learn more about Special folders.
- Learn more about web-accessible resources.

