Bun-native · React 19 SSR · Web-standard boundaries

The full-stack framework built on Bun, not bolted onto it.

Patties is a Bun-native meta-framework. HTTP is Bun.serve, bundling is Bun.build, discovery is Bun.Glob, hot-reload is bun --hot — no Webpack, no chokidar, no node:http wrapper. Filesystem routing and islands are discovered once at build time and inlined, so the production server never re-scans the disk. UI is React 19 over renderToReadableStream.

0
Node-era build tools to wire up
build-time
route & island discovery
React 19
streaming SSR + islands
bun · edge
deploy targets behind adapters
Why it exists

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.

Up in one command

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.

terminal
# 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
app/routes/invoices.ts
// 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())),
  },
};
Standards at the boundary

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.

Where to go next

Five doors into the project

Build with the framework, follow the design intent, track what shipped and what's next, read the human-readable version history, or meet the person behind it.

"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.

Privacy

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.