The starting point for an app with a React frontend. Same server, env,
database and API skeleton as template-htmx — the two differ only in what is
served at / — with a React 19 SPA, Tailwind v4 and shadcn/ui on top.
Carried from a working project rather than designed in the abstract, and
carrying the lessons that cost it time:
- The dev script states NODE_ENV=development rather than inheriting it. React
resolves its runtime against NODE_ENV: Bun emits jsxDEV() in development
and React's production jsx-dev-runtime defines jsxDEV as void 0. Inherit
production while transforming for development and the app dies at first
paint. Verified: the dev bundle resolves the development runtime and
contains no void-0 stub.
- Asset URLs in components are relative and <base href="/"> is in the HTML,
so a path-prefix proxy can rewrite one attribute and every asset follows. A
test enforces it.
- Routing is in the hash, because the app may be mounted under a prefix it
only learns at runtime and a hash means the same thing at either mount.
- index.html holds __PUBLIC_URL__ and gen-index.ts substitutes it, because
Bun's HTML bundler fails the build on a root-relative favicon href.
- APP_ENV failing closed, env files before the ambient environment, the
database enforced by name, one Postgres client per process — as in the
htmx template.
The database has no tables. The App is a shell with one tab and no features,
named as a placeholder. Renaming `app` is the first step and the README lists
every place it appears.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>