█████
a full-stack framework for Bun
Pages, data, server and deploy in one package that depends on nothing.
The name comes with the invite.
v0.0.1 · private preview0 runtime dependenciesbuilt for BunReact firstbuilt by @productdevbookJoin ↓
What it is
We build a full-stack web framework for Bun. You write pages in React, data loaders and server routes in TypeScript, and one command builds the lot.
It is ESM only and built on Web standards: Request, Response, fetch, Web Crypto. Bun and Node APIs stay in the build, the dev server, the CLI and the presets.
// app/pages/posts/[slug].server.ts export const load = defineLoader(({ params, fetch }) => fetch(`/api/posts/${params.slug}`)); // app/pages/posts/[slug].tsx export default function Post() { const post = useData<Post>(); return <article><h1>{post.title}</h1></article>; }
The loader runs on the server. Its fetch reaches the app's own route in the same process, without a network hop.
Zero dependencies
The dependencies field of every package we publish is empty. Not small. Empty.
React is a peer dependency of the React adapter, so your app picks the version. Everything else we wrote: the router, the session seal, the CSRF tokens, the storage drivers, the cache, the OpenAPI document, the GraphQL server, the OTLP exporter.
A React app installs in 8.2 MB of node_modules, React included.1
dependencies.Bun builds, everything runs
Development and builds run on Bun. The output does not need it.
Pick a preset and the same app becomes a Bun server, a Node 24 server, a Cloudflare Worker, a Vercel or Netlify function, or a folder of static files. A production build of the benchmark app takes 0.20 s.1
Against the React frameworks
The same small React app, built five ways: a page with a counter, and /posts, which loads 20 posts from the app's own API route.
We show every row, including the ones we lose.12
| Median of 3 | Next.js 16.4.3 | vinext 1.3.0 | TanStack Start 1.168.61 | Astro 7.3.8 | Ours (Bun) | Ours (Node) |
|---|---|---|---|---|---|---|
Install size, node_modules (MB)3 | 341.6 | 145.9 | 113.9 | 154.6 | 8.2 | 8.2 |
| Production build (s) | 4.11 | 4.06 | 2.05 | 1.89 | 0.20 | 0.22 |
Cold start to first 200 on / (ms) | 563 | 470 | 139 | 224 | 60 | 117 |
SSR /, requests per second | 542 | 421 | 2,788 | 2,551 | 4,228 | 2,644 |
SSR /, p99 latency (ms) | 138.8 | 197.0 | 31.8 | 41.2 | 24.0 | 39.2 |
SSR /posts, requests per second | 429 | 392 | 2,077 | 3,216 | 2,743 | 1,122 |
SSR /posts, p99 latency (ms) | 200.0 | 215.1 | 41.0 | 28.7 | 42.4 | 101.8 |
Client JS for /, gzip (KB)4 | 136.6 | 146.9 | 109.4 | 68.3 | 90.8 | 90.8 |
Client JS for /, raw (KB)4 | 453.6 | 475.2 | 337.8 | 216.1 | 271.8 | 271.8 |
Shaded: best in the row. “Ours” is an unpublished build of the framework.
Our Bun server leads on build time, cold start and /. Astro serves /posts faster and ships less JavaScript, because it hydrates one island and not the page.4 On Node our /posts is behind TanStack Start and Astro.
What's in the box
One package. Each of these is written by us, documented and tested.
A file in app/pages/ is a URL. Params, catch-alls, groups, layouts and route middleware.
A .server.ts file next to the page loads its data on the server. The page reads it with useData().
A file in server/api/ is an endpoint, on Web Request and Response. Methods go in the file name.
Sealed cookie sessions with AES-GCM, CSRF tokens bound to the session, an origin check and security headers on by default.
memory, fs, sqlite, redis, s3 and cloudflare-kv, behind one key-value API.
Cached handlers, cached functions and route rules with stale-while-revalidate. CDN headers follow the same rule.
Routes that carry a Standard Schema are checked, typed and described in an OpenAPI 3.2 document the server builds itself.
Schema in SDL, resolvers in TypeScript. Written by us, with no GraphQL package. Off by default, so an app without it ships none of it.
Logger, request id, request log, tracing with our own OTLP exporter, metrics, Server-Timing. Tracing and metrics cost nothing until you turn them on.
bun, node, static, cloudflare, vercel and netlify. One build command, one output folder.
React is the first. It is not the only one.
The core never imports a UI library. React plugs in through an adapter, and so does whatever comes next.
What else plugs in, we are not saying yet. Applicants hear first.
This page is built with it
You are reading a page of an app made with the framework, written in React and rendered on the server. The browser hydrates it; the only other script is a cookieless analytics tag.
The join form is a plain HTML form in two steps, with a CSRF token, checked on the server and answered with a 303. It works with JavaScript turned off. It runs on Cloudflare Workers, and your email goes to the cloudflare-kv storage driver.
<form method="post" action="/forms/join">
<input type="hidden" name="_csrf" value="…">
…
</form>
→ 400 with the errors, or 303 /join/moreJoin the preview
3 developers on the list
Leave your email and you are on the list. We open it in small groups. We don't have a date yet.
Questions
When do I get access?
We open it in small groups. We don't have a date yet.
Why the secrecy?
Development is closed and the repository is private. We would rather show a finished thing than a moving one. The name comes with the invite.
Is it production-ready?
Not yet. It is a private preview: the numbers on this page are measured, and the API can still change.
Which UI libraries does it support?
React today. The core never imports a UI library, and React plugs in through an adapter. What else plugs in, we are not saying yet.
Do I need Bun?
Bun builds it and runs development. The output runs on Bun, Node 24 or later, Cloudflare Workers, Vercel, Netlify, or as static files.
What do you keep?
Your email, the links and answers you choose to give, your country and the date. Nothing else. No IP address.