Documentation Index
Fetch the complete documentation index at: https://extension.js.org/llms.txt
Use this file to discover all available pages before exploring further.
Extension.js processes HTML entrypoints from two sources: manifest fields and the special pages/ folder. Manifest fields include popup, options, side panel, new tab, and DevTools. Use pages/ for routes the manifest does not name directly.
Extension.js walks each entry for scripts, styles, and linked assets. You author plain HTML and Extension.js configures everything automatically.
Template examples
Minimal new-tab extension with an HTML page entrypoint.
npx extension@latest create my-extension --template=new
Repository: extension-js/examples/new
Side panel extension with an HTML page entry for persistent companion UI.
npx extension@latest create my-extension --template=sidebar
Repository: extension-js/examples/sidebar
HTML capabilities
| Capability | What it gives you |
|---|
| Entrypoint discovery | Compile HTML declared in manifest and pages/ with one flow |
| Asset wiring | Bundle referenced scripts and styles from HTML tags |
| Public path handling | Keep intentional public-root assets stable |
| Dev tracking | Recompile on HTML and referenced asset edits |
Supported HTML entrypoints
The following manifest fields use HTML files as entrypoints:
| Manifest field | File type expected |
|---|
action.default_popup | .html |
background.page | .html |
chrome_url_overrides.* | .html |
devtools_page | .html |
options_ui.page / options_page | .html |
page_action.default_popup | .html |
sandbox.pages | .html |
side_panel.default_path | .html |
sidebar_action.default_panel | .html |
You can also add standalone pages under pages/ without expanding manifest entrypoint fields for every file.
Sample HTML entry
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Extension Page</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div id="app"></div>
<script src="./main.ts"></script>
</body>
</html>
How Extension.js processes HTML
For each HTML entrypoint, Extension.js:
- Emits the HTML file into compilation.
- Discovers local scripts/styles/static assets from tags.
- Bundles scripts/styles as proper extension outputs.
- Patches HTML to inject compiled bundle references.
- Keeps public-root references (like
/icon.png) as public assets.
Development behavior
- Extension.js tracks HTML and referenced assets in file dependencies, so edits trigger recompilation.
- Script changes use hot module replacement (HMR) where supported in the injected script flow.
- If the HTML script/style entry list changes (add/remove entries), Extension.js can require a dev server restart.
- Changing manifest HTML entrypoints can also trigger restart-required diagnostics.
Paths and environment variables
- Extension.js resolves relative paths from the HTML file location.
- Extension.js treats leading
/ paths as extension public-root paths.
- Extension.js replaces
$EXTENSION_PUBLIC_* and related placeholders in emitted HTML during compilation.
Place extra files in pages/:
pages/
└── extra-page.html
Common extension surfaces
Most extension surfaces that render UI are HTML entrypoints with different manifest fields and runtime expectations. Use the surface that matches your interaction model, then keep the HTML page itself thin.
| Surface | Manifest field | Good fit |
|---|
| Popup | action.default_popup or browser_action.default_popup | short, task-focused UI opened from the toolbar |
| Options page | options_ui.page or options_page | durable settings and preferences |
| Side panel | side_panel.default_path or sidebar_action.default_panel | persistent companion UI alongside the current tab |
| DevTools page | devtools_page | debugging or inspection tools for your extension |
| New tab override | chrome_url_overrides.newtab | full-screen extension-owned browser surface |
| Sandbox page | sandbox.pages | isolated HTML when sandboxed execution is required |
Use a popup for fast, focused actions:
- Quick status checks.
- One-step commands.
- Small forms or toggles.
Keep popups small and resilient. Popups open and close frequently, so avoid assuming long-lived in-memory UI state.
Options page
Use an options page when you need to configure durable behavior:
- Account or integration settings.
- Feature toggles.
- Keyboard or workflow preferences.
Pair options pages with browser storage so settings survive restarts and background or content-script code can read them.
Side panel
Use a side panel when the extension needs a persistent workspace next to the current page:
- Research or note-taking companions.
- Tab-aware assistants.
- Page analysis results that should stay visible while you navigate.
Side panel HTML is still an extension page entrypoint. The difference is the surface semantics, not the build pipeline.
DevTools page
Use devtools_page when the extension provides tooling for developers:
- Inspection panels.
- Request or DOM diagnostics.
- Project-specific debugging helpers.
Treat this as a specialized surface. It usually needs stronger messaging patterns because it often coordinates with background logic and inspected tabs.
New tab override
Use chrome_url_overrides.newtab when the extension owns the whole new-tab experience.
This is usually the best fit for rich, app-like UIs where a popup would be too constrained.
Sandbox page
Use sandbox pages only when the feature truly needs the sandbox model. They are HTML entrypoints too, but they exist for a narrower set of browser-extension security and execution constraints.
Surface authoring pattern
A good default structure for any HTML surface is:
- Keep the HTML file minimal.
- Mount one script entry.
- Import styles from that script or a linked stylesheet.
- Move browser API coordination into dedicated modules.
That pattern works well for popup, options, side panel, DevTools, and new-tab surfaces.
Best practices
- Keep entry HTML minimal and import app code through scripts.
- Use relative paths for project assets and
/ paths only for intentional public assets.
- Use
pages/ for additional extension pages that are not primary manifest UI entrypoints.
- Treat script/link add/remove changes as structural changes that may require restart.
- Choose the surface by user interaction model first, then implement it as a thin HTML page entrypoint.
- Keep surface-specific state in storage or background coordination instead of assuming the UI page always stays mounted.
Next steps