Bootstrapping a Product
The assembly sequence for a new product conforming to the architecture standard. Until the template repo exists, this is a hand-assembled checklist; the invariants in the standard’s §13 are the acceptance test.
The skeleton, in order
- Root scaffold:
package.json(themarketingworkspace + the build pipeline scripts),vite.config.ts,wrangler.jsonc, both tsconfigs,app.html,scripts/merge-marketing.mjs. - Cross-surface boundaries: top-level
config/(brand.ts,routes.ts— pure typed data) andstyles/(tokens.css), with the#config/*subpath import declared inpackage.json"imports"and mirrored in all three tsconfigs andvite.config.ts. src/three-folder split:client/(main.tsx, App.tsx, api.ts, i18n.tsx, pages/, components/ui + features, lib/),worker/(index.ts, routes/ with middleware.ts, services/, db/),shared/(types.ts + domain helpers).- The serving contract: the Worker catch-all using
isAppPath()fromconfig/routes.ts,app.htmlas the SPA shell, nonot_found_handling, marketing owningindex.html. marketing/Astro workspace importingstyles/tokens.cssand#config/*; static output; built-in i18n with an unprefixed default locale.migrations/,test/,docs/conventions; runwrangler typesand wirenpm run check.
Backend-internal conventions — auth shape, testing bar, env validation — are a later phase (standard §10–§12); copy the reference implementation as a starting point.
What changes per product: the domain and wrangler name, the Env bindings
and DB name, the route modules and service/db domains, the config/ values
and token palette, and the marketing content. The shape stays identical.
Verifying the serving model
Run this after assembly and after any change to the serving model — there are no route-level tests for it, so the check is manual and cheap.
npm run build && npm run previewThen assert each path returns the expected source and status:
/ 200 (marketing) /<section> 200 (shell)
/pricing/ 200 (marketing) /<section>/ 200 (shell)
/admin/<page> 200 (shell) /<res>/<slug> 200 (shell)
/<res> 404 (marketing) /garbage 404 (marketing)
/api/nope 404 (JSON)The failure modes this catches: a SPA shell served with 200 for garbage URLs
(missing catch-all logic), marketing pages falling through to the shell
(asset merge broke), or app paths 404ing (drift between config/routes.ts
and the mounted routes — which the test/routes.test.ts boundary pins should
also catch).
Finish with the full gate:
npm run check && npm test