Start from Bun's primitives, delete the rest
Most full-stack frameworks were designed in the Node era and carry its tooling tax: a bundler bolted on, a separate file watcher, a glob library, an HTTP layer wrapped around node:http. Bun ships all of that natively. Patties is what a framework looks like when you build on those primitives instead of re-importing the stack on top of them.
Bun.serve at the core
HTTP comes straight from Bun.serve. Handlers receive a standard Request and return a standard Response — no server abstraction in between.
Filesystem routing
Routes are files under app/routes/, compiled to Bun route patterns. Dynamic segments, methods, and nesting — discovered, not configured.
React 19 + islands
Pages render on the server with renderToReadableStream. Mark a component an island and only it ships to the client, hydrating on demand.
Discover at build, serve frozen
Route + island discovery happens once during build and is inlined into the bundle. The production server runs a static table and scans nothing.
Thin context
The one framework affordance is PattiesContext — params, cookies, env, vars, and json/html/redirect. Standards at the boundary, kept deliberately small.
Adapters, not lock-in
Deployment targets (bun, edge) live behind adapters. Platform specifics stay out of the core, so the same app ships to more than one place.
Copy-in UI catalog
patties-ui is a shadcn-compatible, copy-in catalog of 60 components. patties add <component> stamps the source into your app — never a versioned dependency.
Optional AI primitives
Agents, tools, and jobs ride on an optional @anthropic-ai/sdk peer dep. Non-AI apps install and run without it; the AI surface loads only when used.
Plugins & AGENTS.md
Hook into build, dev, and jobs. patties dev/build regenerate an inventory of your app into CLAUDE.md/AGENTS.md for coding agents.
Scaffold an app, then dev
The official scaffolder, create-patties, asks a few questions — project type, Patties UI, monorepo, deploy target — and stamps a working app. Then patties dev gives you Bun-native HMR with a single copy of React.
Routes are folders, handlers are functions, and the only import you need to learn is the one that was already there.
# scaffold a new app
bunx create-patties@latest my-app
cd my-app
# Bun-native dev server with HMR
bunx patties dev
# build (route + island discovery happens here) and ship
bunx patties build
bunx patties deploy
// A route module — a plain function over web standards.
// Discovered at build time and inlined into the Bun.serve table.
export const routes = {
"/invoices/:id": {
GET: (req, ctx) => ctx.json({ id: ctx.params.id }),
},
"/invoices": {
POST: async (req, ctx) =>
ctx.json(await create(await req.json())),
},
};
Handlers are just functions
A handler takes a standard Request and a thin PattiesContext, and returns a standard Response. Request flow is plain compose() middleware — no guards, pipes, interceptors, or decorators.
The same shape underlies the design exploration: a modular monolith where modules talk only through a published public API, enforced by one build-time boundary check.
Four doors into the project
Build with the framework, follow the design intent, track what shipped and what's next, or read the human-readable version history.
Documentation
Guides and reference: routing, rendering, the build pipeline, the CLI, and deployment. Start here to build something.
Releases & roadmap
What's shipped and what's coming — the delivery tracker, plus the status of every design specification.
Changelog
The human-readable version history — what landed in each release of patties, create-patties, and patties-ui, newest first.
Design specs
The modular-monolith design exploration: architecture, features, and the decision records behind the framework.
"A framework you could delete and still have an app."
Fewer dependencies, web-standard boundaries, and the expensive thinking done at build time. Reach for a Bun or web primitive every time one exists — the framework is the thin layer that's left.
Analytics & cookies
This site ships with optional, privacy-first Google Analytics 4 support that is disabled by default: no measurement ID is configured, so no Google script loads, no cookie is set, and no consent banner is shown. If analytics is later enabled, it runs under Google Consent Mode v2 with every signal defaulting to denied until you accept. The framework and your apps are wholly unaffected — this concerns the documentation website only.