🥖 BATCH · Substrate
No build. Just ship the source.
BATCH is a no-build, server-rendered hypermedia substrate on Bun. It's the bottom layer that GRAIN and the product stand on. Bun runs the TypeScript directly, so the browser gets near-zero framework JavaScript. The whole point is to show that modern HTML, CSS, and a small runtime don't need a bundler.
Live · runs this siteWhat it is
No build step
Nothing between source and server: no bundler, no transpiler. Ship the source, the runtime reads it.
Server-first, not no-JS
The portfolio sends complete pages, then adds JavaScript for shared interactions. That app-wide script weight belongs in the story too.
Zero runtime deps
Third-party runtime dependencies stay at zero (today, only Bun). Platform builtins and dev tools don't count.
Addressable and operable
Every surface has a semantic address: the base a person and an AI can both drive. That part is GRAIN, above.
Static export = projection
Export crawls the running server and freezes it to static files, never a second renderer, so the export can't drift from the app.
Audit engine built in
A framework-generic perf + SEO/AEO harness benches any app, not just this one. The numbers are the proof.
What the portfolio audit measured
On , a headless Chromium run measured 211,553 bytes of JavaScript on /batch, within 745,209 total transferred bytes across 35 requests. Deferring live-figure code to the pages that use it cut 56,053 JavaScript bytes from the earlier run. That is the portfolio page and its shared shell, not a benchmark of a minimal BATCH app by itself.
Run bun run audit from the portfolio repository to repeat the check. The
full report
covers all 148 routes and notes the limits of local timing measurements.
The reference
The canonical docs are homed here and render through MILL, at /batch/docs:
Where it sits in the stack
Part of the BREAD stack, alongside GRAIN, MILL, PROOF, CRUMB, and PANTRY.
AI helps me write and review. I direct the work, test the result, and answer for what ships. How I work with AI →