Templates
Embedded scaffolding used by the CLI to create projects and generate files. Keeps new apps consistent and zero-config.
Overview
- Repo source of truth lives under
orchestrators/bun/resources/templates/**. - Generated package assets live under
orchestrators/bun/assets/templates/**and are embedded into the Bun CLI package. webstir initlays down a server-firstfullproject by default.- Generators add files in the right place with sensible defaults.
Layout
Created by webstir init according to workspace mode:
full: frontend, backend, shared, and typesspa: frontend, shared, and typesssg: frontend and typesapi: backend, shared, and types
Typical frontend scaffold:
src/frontend/app/app.htmlsrc/frontend/app/**src/frontend/pages/<page>/index.html|css|tssrc/frontend/{content,images,fonts,media}/**
Typical backend scaffold:
src/backend/index.tssrc/backend/module.tssrc/backend/jobs/**src/backend/tests/**
Conventions
- Base HTML requires a
<main>insrc/frontend/app/app.htmlfor page merge. - Page folder names must be URL-safe: letters, numbers,
_and-. - Each page has
index.html,index.css,index.ts. - Backend entry is
src/backend/index.ts. - Fresh
apiandfullscaffolds keepsrc/backend/index.tsthin and use it to boot the package-managed Bun runtime. - Manifest-backed route and demo logic lives in
src/backend/module.ts. - The default app primitives are documented in Primitives; treat that page as the naming contract for pages, forms, actions, fragment targets, request-time views, and auth-gated routes.
- For optional app features, prefer absolute app-asset imports such as
await import('/app/router.js')so dev and publish paths stay aligned. - Start with
fullwhen the app needs forms, redirects, auth, or server-rendered documents; opt intospaorssgonly when you need those delivery modes specifically.
TypeScript
- Uses an embedded
base.tsconfig.jsonreferenced by template tsconfigs. - ESM-only; compiled via the active provider packages.
- Shared code in
src/sharedis compiled for both frontend and backend. - Dev output keeps source maps for local debugging; publish strips them.
- Dynamic imports load at runtime. Keep
/app/...imports absolute for assets undersrc/frontend/app/.
CSS & Assets
- Plain CSS by default; optional CSS Modules in publish.
@importand asset URLs are resolved; files copied to outputs.- Place static app assets under
src/frontend/app/*. - Place Images, Fonts, and Media under
src/frontend/{images|fonts|media}/**.
Client Error Reporting
- The base
app.htmlincludes/app/error.jswhich installs a lightweight client error handler. - It listens for
windowerrorandunhandledrejectionand reports toPOST /client-errorsusingsendBeacon(fallback tofetch). - Behavior:
- Throttled: max 1 event/second; capped at 20 per page session.
- Deduped: repeats suppressed within 60s using a fingerprint of type|message|file:line:col|stack-hash.
- Correlation: includes a client correlation id; server also accepts
X-Correlation-ID.
- Override: set
window.__WEBSTIR_ON_ERROR__ = (event) => { /* custom */ }before errors occur to customize reporting. - Opt-out: remove the
<script src="/app/error.js" async></script>tag from yoursrc/frontend/app/app.html.
Generators
add-page
- Command:
webstir add-page <name> --workspace <path> - Delegates to
webstir-frontend add-page(TypeScript CLI) to scaffoldindex.html|css|ts. - Does not modify existing pages or
app.html. - Name normalization: trims, lowercases, replaces spaces with
-.
add-test
- Command:
webstir add-test <name-or-path> --workspace <path> - Delegates to
webstir-testing-add(TypeScript CLI) to create<name>.test.tsunder the nearesttests/directory. - Works for both frontend and backend tests.
Backend Template
- Thin Bun bootstrap at
src/backend/index.ts. - Manifest-backed route and demo logic at
src/backend/module.ts. - Exposes health endpoints (
GET /api/health+/healthz) and a readiness probe (/readyz) that returns the manifest summary. - Reads
PORTenv var; defaults handled by the CLI dev server proxy in dev. - Optional auth adapter: set
AUTH_JWT_SECRET(plusAUTH_JWT_ISSUER/AUTH_JWT_AUDIENCEandAUTH_SERVICE_TOKENSwhen needed) to enable bearer-token verification and populatectx.authin module routes. - Observability: install
pino, setLOG_LEVEL/LOG_SERVICE_NAME, and enable metrics viaMETRICS_ENABLED. Every request logs structured JSON and/metricsexposes rolling latency/error stats. - Database & migrations: set
DATABASE_URL(defaults to SQLite in./data/dev.sqlite) and manage schema changes viasrc/backend/db/migrate.ts+src/backend/db/migrations/*.ts. The scaffolded helper usesBun.SQLfor both SQLite (file:./data/dev.sqlite,sqlite:./data/dev.sqlite,:memory:) and Postgres (postgres://...), so the same Bun-native client works across both paths without an extrapginstall. - Jobs & scheduling:
src/backend/jobs/**plusbuild/backend/jobs/scheduler.jssupport one-off runs, manifest export, and local watch-mode execution. On Bun1.3.11+, the built-in scheduler usesBun.cron.parse(...)for real cron expressions and nicknames while still preservingrate(...)and@rebootschedules for local development loops.
Publish Outputs
- Per page:
dist/frontend/pages/<page>/index.html - Fingerprinted assets:
dist/frontend/pages/<page>/index.<timestamp>.{css|js} - Per-page
manifest.jsonlisting hashed asset names. - App assets copied to
dist/frontend/app/*.
Customizing Templates
- Edit templates under
orchestrators/bun/resources/templates/. - Treat
orchestrators/bun/resources/features/client_nav/**as the canonical source for the built-inclient-navfiles projected into thefulltemplate. - Regenerate the shipped package assets with
bun run --filter @webstir-io/webstir buildorcd orchestrators/bun && bun scripts/sync-assets.mjs. - Use
bun run --filter @webstir-io/webstir check:assetsto verify the generated tree is still in sync. - Use
bun run --filter @webstir-io/webstir check:feature-projectionsto verify the exactclient-navtemplate projections still match their shared feature sources. - Keep conventions intact (page structure, base HTML
<main>, server entry path). - After changes, rebuild the CLI to embed updated templates.