Skip to content

Repo tour

ExtensionStart is a pnpm + Turborepo monorepo. Here’s the map, top to bottom.

WXT + React 19 + Tailwind 4 + Firebase. WXT generates manifest.json from wxt.config.ts per browser; never hand-edit a manifest.

  • entrypoints/background/: one module per concern, imported by index.ts in a fixed order: migrationserrorslogsfirebase (auth) → billinggatesbroadcastsupdate-notice. All event listeners are registered at the top level (why that matters).
  • Surfaces: popup and sidepanel mount the same account/settings tabs (no separate options page); welcome is the first-run tour; content holds the shadow-DOM UI: status bar, gate walls, highlighter demo; offscreen is the auth fallback. Demo surfaces newtab and devtools build only with WXT_DEMO_SURFACES=true.
  • utils/: the typed messaging protocol, settings store, shadow-UI mount, DOM observer, highlight persistence, error reporting, page bridge.
  • hooks/: useAuth, useBilling, useTheme.
  • site.config.ts: every user-facing name, email, URL, and pricing-copy string. Rebranding starts (and mostly ends) here.

Each package is a framework-free core with a thin React subpath (/react) where UI bindings exist. Lint enforces importing only public entrypoints.

package what it is
core-ext defineStore / defineStorageView / defineMessaging / defineProxyService / defineAlarm / defineMigrations (the MV3 survival kit) plus a /testing chrome mock
core-auth auth strategies (web-auth-flow default, offscreen fallback), anonymous-first linking, typed auth errors
core-billing entitlement snapshot + states matrix, billing API client, storage-backed hooks (useEntitlement('paid'))
gate trigger primitives and combinators, the gate evaluator (cooldowns/escalation/chaining), presets, and the GateWall UI (/react)
ui Button/Card/Input/Badge/Skeleton/Dialog/Toast (CVA variants over Base UI)

A single Hono app on Cloud Functions v2, deliberately self-contained: Firebase packs it standalone, so it can’t import workspace TypeScript. Routes: /gateConfig, /billing/checkout, /billing/portal, /billing/webhook, /gate/events, /auth/revoke, /errors. The billing core is port-based (StripeGateway / EntitlementStore / ClaimsWriter) so alternative payment providers can implement the same contract.

  • create/: the create-extstart wizard (reference).
  • config/: shared ESLint/Prettier/tsconfig presets and the module.schema.json that validates module manifests.

Every prunable feature module carries a module.json manifest declaring its files, dependencies, env vars, and manifest permissions. The wizard’s pruner consumes these: dropping a module removes its code, deps, env entries, and permissions together. Details in the module system guide.

From the repo root:

Terminal window
pnpm build # build everything
pnpm typecheck # TypeScript, strict, workspace-wide
pnpm lint # ESLint, workspace-wide
pnpm turbo run test # unit tests

Extension-specific root aliases (the long form pnpm --filter @extensionstart/extension <script> always works too):

Terminal window
pnpm dev # dev build + watch
pnpm e2e # Playwright against the built extension
pnpm zip # store-ready zip (also zip:firefox, zip:edge)
pnpm audit:remote-code # scan built output

Backend (from backend/functions/): pnpm serve (emulators), pnpm firebase:deploy, pnpm seed:stripe, pnpm stripe:webhook, pnpm doctor, pnpm test, pnpm test:rules, pnpm test:lifecycle.