Quick Start
Scaffold an Extro extension, run the dev server, and load it in Chrome.
Quick start
Scaffold a project:
pnpm create extro my-extensionnpm create extro@latest my-extensionyarn create extro my-extensionbun create extro my-extensionStart the dev server:
cd my-extension
pnpm devLoad it in Chrome: open chrome://extensions, enable Developer mode (top right), click Load unpacked, and select output/chrome-mv3-dev/. Pin the extension and click its icon.
That's a running extension with HMR. Edit src/app/popup/page.tsx and the popup hot-reloads with state preserved.
Requirements
- Node.js 20+
- A package manager (pnpm, npm, yarn, or bun). Examples in these docs use pnpm.
- Chrome or any Chromium-based browser.
Manual setup
To add Extro to an existing project, install it yourself:
pnpm add extrojs react react-domextrojs is the whole framework: the CLI, the Vite plugin, and the runtime you import in app code through subpaths (extrojs/link, extrojs/navigation, extrojs/asset). It is the only Extro package you add. react and react-dom are peer dependencies, needed for the React surfaces (popup, options, sidepanel, CSUI); a script-only extension can skip them.
Add the scripts to package.json:
{
"scripts": {
"dev": "extro dev",
"build": "extro build"
}
}Add an extro.config.ts:
import { defineConfig } from "extrojs"
export default defineConfig({
name: "My Extension",
description: "A Chrome extension built with Extro.",
permissions: ["storage"],
})And your first surface:
export default function Popup() {
return <h1>Hello from Extro.</h1>
}That is enough. The popup is a real React tree, file-based, picked up automatically.
The dev loop
pnpm dev does an initial build so output/chrome-mv3-dev/ is loadable, then starts a Vite dev server. The manifest and HTML shells in the dev output point at http://localhost:<port>, so HMR works against a real extension. You load the unpacked directory once; restarts of extro dev do not require reloading the extension.
Good to know
Dev and prod builds live in separate directories (output/chrome-mv3-dev/ and output/chrome-mv3-prod/), so a production build never invalidates the unpacked dev extension you loaded.
Production build
pnpm buildThis writes a fully bundled, minified extension to output/chrome-mv3-prod/. See Building for Production.