Setup wizard
create-extstart configures your clone in place. It downloads
nothing, touches no files outside the repo, and refuses to run on a dirty
git tree, so every change is one git diff away from review and one
git checkout away from undo.
pnpm create extstart # run from anywhere inside the cloneWhat it does, in order
Section titled “What it does, in order”- Questionnaire: extension name and description (written to
apps/extension/site.config.ts), scope, target browsers, a monetization model ifbillingis kept, and a gate preset ifgateis kept. - The plan: prints every file, dependency, permission, and env entry it will remove. Nothing changes until you confirm.
- Pruning: executes the plan, driven by each module’s
module.jsonand itsmodule:<id>wiring markers (module system). - Marker cleanup: strips the remaining
module:*marker comments from kept files; the code stays. Opt out with--keep-markers(Rerunning). - Env scaffold: creates
apps/extension/.envfrom the pruned.env.example, prompting per variable. An existing.envis left untouched. - Firebase setup (optional): creates or picks a Firebase project and writes its config everywhere it lives. Decline freely; it reruns standalone any time (below).
- Backend pointers: prints the Stripe setup commands and offers to run the backend doctor.
- Verify pass: regenerates WXT types and typechecks the pruned tree;
--with-testsadds the unit suites.
The scope question
Section titled “The scope question”One question before any per-module prompt: start minimal or keep everything?
- minimal: what a monetized popup extension needs:
billing,gate, and thesitewebsite template. Everything else is onegit checkoutaway later. - everything: keep every optional module (same as
--yes). - choose: the per-module walkthrough, in dependency order.
If unsure, keep everything; trimming later is easier than restoring from git history.
The optional modules
Section titled “The optional modules”| id | what you get | drop it when |
|---|---|---|
billing | Stripe checkout/portal, webhook-written entitlements, pricing UI | your extension is free |
gate | sign-in walls and paywalls with timing presets (requires billing) | you have no walls to show |
sidepanel | the account/settings UI docked in Chrome’s side panel | your product is popup-only |
site | your extension’s public website: landing, privacy policy, terms | you already have a website |
broadcasts | remote banner announcements + the post-update changelog notice | you never need to reach installs between releases |
error-reporting | consent-gated crash reports to your own backend (defaults to No) | you don’t want crash telemetry |
content-demo | the highlighter demo (the shadow-UI mount itself always stays) | always, once you’ve read its source |
demo-newtab | new-tab override demo (builds only with WXT_DEMO_SURFACES=true) | you don’t ship a new-tab surface |
demo-devtools | devtools panel streaming the support log (same build flag) | you don’t need it |
Core modules (auth, the extension core, UI primitives) are not removable.
Dependencies resolve automatically: keeping gate force-keeps billing;
dropping billing drops gate too. The pruner leaves backend/** in
place for dropped modules; the backend is one self-contained function and
unused routes are harmless.
Firebase setup (--firebase)
Section titled “Firebase setup (--firebase)”The Firebase step runs standalone: no questionnaire, no prune, no clean-tree requirement, safe to re-run.
pnpm create extstart --firebaseIt creates or picks a project, writes the SDK config into every file that carries it, and prints a deep-linked checklist of the console steps no CLI can do (sign-in providers, Blaze plan, OAuth client). Walkthrough: Sign-in guide.
Headless mode
Section titled “Headless mode”pnpm create extstart --yes --scope minimal --name "My Ext"pnpm create extstart --dry-run --scope minimal # print the plan only--yes accepts defaults with no prompts and keeps everything unless
--scope or --keep says otherwise. Full flag list:
CLI reference.
Rerunning
Section titled “Rerunning”The wizard is built for one configuration pass on a fresh clone. To
experiment, run it, inspect git diff, and git reset --hard to try a
different combination.
Marker cleanup is the default, so a second pass can rebrand but no longer
prune. Run the first pass with --keep-markers to keep pruning open.
Adding a module back after committing means restoring its files from git
history, so keep what you are unsure about.