# app A project started from `template-react`. **Rename `app` first** — README step 1. **Bun · Hono · React 19 · Tailwind v4 · shadcn/ui · Postgres with Drizzle.** ## Read these before writing code | | | |---|---| | `CONVENTIONS.md` | React patterns — feature folders, manager hooks, colocated state — and layout | | `docs/DATABASE.md` | Drizzle structure, `push` not migrations, `check()` vs open `text` | | `docs/SURFACES.md` | The JSON API and the app: one process, one query layer | | `README.md` | Setup, scripts, configuration | ## Rules that are load-bearing **`APP_ENV`, never `NODE_ENV`.** Must be `production` or `development`; throws when unset. Hosts export `NODE_ENV=production` into everything they spawn, so anything keyed on it treats development as production silently. `NODE_ENV` is still set explicitly by both scripts because React's runtime resolves against it — Bun emits `jsxDEV()` in development and React's production runtime defines it as `void 0`. **Env files are read with the ambient environment LAST**: `.env.production.local` (production only) → `.env.local` → `.env` → `process.env`. **Asset URLs in components are relative — never start with `/`.** `` in `index.html` is what a path-prefix proxy rewrites; a leading slash bypasses it. `asset-urls.test.ts` enforces this. `fetch('/api/...')` is the exception. **Routing is in the hash.** The app may be mounted under a prefix it only learns at runtime, and a hash means the same thing at either mount point. `lib/routes.ts`. **One feature folder per screen, one manager hook per feature.** State lives in the hook, components receive the manager. `CONVENTIONS.md`. **Serializers live in `src/servers/serialize.ts` only.** Its test walks the module's exports for camelCase keys and for serializers without a case. ## Bun - `bun ` not `node`, `bun test` not jest/vitest, `bun install`, `bunx` - `Bun.serve()` — not express. `Bun.file` over `node:fs`. `Bun.$` over execa - Bun loads `.env` automatically; do not add dotenv - `bun dev` and `bun start` set the env markers. Running `src/server.ts` directly throws, by design ## Before you finish - `bunx tsc --noEmit` and `bun test` - Verify claims rather than asserting them — start the server and request the thing - Commit with a message that says *why*, not what the diff already shows