Template
Initial commit: Bun · Hono · React SPA · Postgres/Drizzle template
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>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import tailwind from "bun-plugin-tailwind";
|
||||
import { rm } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
const outdir = path.join(process.cwd(), "dist");
|
||||
await rm(outdir, { recursive: true, force: true });
|
||||
|
||||
// Only the generated HTML. The tracked index.html still holds __PUBLIC_URL__ placeholders, and
|
||||
// building it would emit a page whose favicon hrefs are the literal placeholder text.
|
||||
const entrypoints = [...new Bun.Glob("src/**/*.gen.html").scanSync()];
|
||||
|
||||
const result = await Bun.build({
|
||||
entrypoints,
|
||||
outdir,
|
||||
plugins: [tailwind],
|
||||
minify: true,
|
||||
target: "browser",
|
||||
sourcemap: "linked",
|
||||
define: {
|
||||
"process.env.NODE_ENV": JSON.stringify("production"),
|
||||
},
|
||||
});
|
||||
|
||||
for (const output of result.outputs) {
|
||||
console.log(` ${path.relative(process.cwd(), output.path)} ${(output.size / 1024).toFixed(1)} KB`);
|
||||
}
|
||||
Reference in New Issue
Block a user