extro

Dev Mode

What extro dev runs, how each surface hot-reloads, and when a restart is needed.

extro dev gives a real, loaded extension the dev loop of a normal React app. This page explains what it runs and exactly what happens when you edit each kind of file.

What extro dev runs

  1. An initial build, so output/chrome-mv3-dev/ is loadable immediately.
  2. A Vite dev server serving the routable surfaces (popup, options, sidepanel) over http://localhost:<port>. The dev HTML shells point at it, which is what makes real HMR possible inside an extension page.
  3. A build-watch sidecar that rebuilds background.js and content.js on change. Script surfaces can't load from a dev server, so they are rebuilt to disk.
  4. A dev bridge: a small client bundled into the background service worker (even if you have no background file) that connects to the CLI over a WebSocket and applies updates, reloading the extension or remounting content UIs as needed.

Stopping extro dev (Ctrl-C) leaves the dev bundle on disk, and dev artifacts persist across sessions, so you load the unpacked extension once and keep it loaded.

What happens when you edit

You editWhat happensPage reload?
A page, layout, or component in a routable surfaceReact Fast Refresh, state preservedNo
Adding or removing a page.tsx in an existing surfaceRoutes hot-updateNo
content/page.tsx (CSUI) or its importsNew component soft-remounts in the host page, local state resetsNo
content/index.ts (no CSUI)Matching tabs reloadTab reloads
background/index.tsExtension reloads (the only way to swap a service worker)Extension reloads
extro.config.ts or .env filesNothing until you restart extro devRestart
Creating a brand-new surface folderRestart extro dev (entry inputs are fixed at startup)Restart

CSUI edits reset component state

React Fast Refresh needs modules served live from the dev server, and a content script can only run from the bundle on disk. Editing a CSUI therefore rebuilds content.js and remounts the component fresh: the host page does not reload, but useState and other local state reset. State-preserving Fast Refresh for CSUI is tracked in #2.

The offline screen

If you open a surface while the dev server isn't running, the page shows a branded "Dev server isn't running" screen instead of a blank page. It appears only when the server is actually unreachable; start extro dev and reopen the surface.

Ports

PortUsed forConfigure
5173 (auto-increments)The Vite dev serverdev.port, dev.strictPort
9012The dev bridge WebSocketdev.bridgePort

The bridge port is fixed rather than random so the port baked into an already-loaded extension keeps working across extro dev restarts. If 9012 is taken on your machine, set dev.bridgePort in config.

Good to know

Only one extro dev can run per bridge port. A second project needs a different dev.bridgePort, otherwise it exits with "Signal port 9012 is in use".

Dev-only manifest changes

The dev manifest relaxes the content security policy to allow the Vite origin and the dev WebSockets, forces a background service worker (it hosts the bridge), and adds the tabs permission so the bridge can reload matching tabs. The tabs addition applies even when you supply your own permissions list, so dev tab reloads always work. The production build has none of this. See Manifest Generation.

On this page