Thin application bootstrap shell for Spectre apps. It wires a root element to route definitions, starts the router, imports shared shell styles, and exposes a small readiness signal.
Part of the PHCDevworks Spectre shell ecosystem — composable, zero-dependency packages for client-side shell applications.
Contributing | Changelog | Roadmap | Security Policy
- You are wiring a Spectre app into a DOM root and need bootstrap lifecycle management.
- You want optional
beforeMount/afterMountcallbacks and abootReadysignal without writing the plumbing yourself. - You are composing
@phcdevworks/spectre-shell-routerand@phcdevworks/spectre-shell-signalsinto a working shell.
- You need a full application framework — this package handles startup only.
- You need server-side rendering, SSR hydration, or meta-framework integration.
- You need application state, domain logic, or component rendering — those belong downstream.
- Bootstraps a Spectre app into a provided root element.
- Accepts route factories compatible with
@phcdevworks/spectre-shell-router. - Runs optional
beforeMountandafterMountlifecycle callbacks. - Exposes
bootReadyas a reactive signal. - Loads package-level shell styles through
./styles.js.
npm install @phcdevworks/spectre-shellimport { bootstrapApp } from '@phcdevworks/spectre-shell'
const root = document.querySelector<HTMLElement>('#app')
if (!root) {
throw new Error('Missing #app root element.')
}
bootstrapApp({
root,
routes: () => [
{
path: '/',
loader: async () => ({
render({ root }) {
root.textContent = 'Ready'
},
}),
},
],
})When bootstrapApp() is called, the shell runs the following steps in order:
beforeMount()— optional callback fires before route registration.routes()— the route factory is called and routes are collected.new Router(routes, root)— routing control is handed to@phcdevworks/spectre-shell-router.bootReady.value = true— the readiness signal is set.afterMount()— optional callback fires after the router is running andbootReadyis set.
Steps 1–4 are wrapped in an error boundary. Failures throw [spectre-shell] Bootstrap failed: <message> with the original error preserved as cause. If afterMount fires, bootstrap succeeded.
bootstrapApp(options)runs the shell bootstrap flow.bootReadyis a signal that becomestrueafter the router starts.BootstrapOptionsdefinesroot,routes,beforeMount, andafterMount.
This package owns the bootstrap surface between an app root and Spectre routing primitives. It does not own route matching internals, general-purpose state management, component rendering, persistence, design tokens, or framework adapters.
npm install
npm run checkUseful scripts:
npm run typecheckvalidates TypeScript without emitting files.npm run lintruns ESLint.npm run testruns the Vitest suite once.npm run buildemits declarations and JavaScript todist.npm run checkruns the standard package verification flow.
AI-agent coordination starts in AGENTS.md, with companion guidance in CLAUDE.md, CODEX.md, COPILOT.md, JULES.md, and .github/copilot-instructions.md.
| Problem | Likely cause | Fix |
|---|---|---|
npm run check fails on typecheck |
Type error in source or tests | Run npm run typecheck to isolate |
| Tests fail in CI but pass locally | Node version mismatch | CI runs Node 22 and 24; match locally |
dist/ is missing after clone |
Build output is gitignored | Run npm run build |
bootReady stays false |
Bootstrap threw before setting signal | Check for errors in beforeMount or routes() |
| Styles not applied | styles.js side-effect not imported |
bootstrapApp handles this; verify sideEffects in bundler config |
See CONTRIBUTING.md. The gate is npm run check — all of typecheck, lint, build, and tests must pass. Do not add routing logic, state management, or rendering to this package; see AGENTS.md for boundaries.
See CHANGELOG.md.
MIT. See LICENSE.