Reora is a Bun-native React framework prototype with:
- server components by default
'use client'graph splitting- file-level
'use server'actions 'use cache'wrapping with request and process caches- a small custom Flight-style protocol
- Bun-native build, dev, and production server flows
The repo is organized as a workspace:
apps/
playground/ # example app
packages/
compiler/ # scan, graph, transform, emit, build
protocol/ # custom Flight-style wire format
runtime/ # server, render, cache, actions, dev session
reora/ # public package and CLI
test/ # compiler, protocol, cache, and server integration testsInstall dependencies:
bun installRun the playground in development:
bun run devThis command intentionally starts the Reora dev server directly. Reora already watches app and workspace source files for rebuilds, so wrapping it with bun --watch causes conflicting restarts during app edits.
Create a production build:
bun run buildStart the production server from build artifacts:
bun run startRun checks:
bun run test
bun run typecheckReora looks for application code under src/ and routes under src/app/.
src/
app/
page.tsx
about/page.tsx
posts/[id]/page.tsx
api/route.ts
actions.ts
components/
lib/
styles/
globals.css
reora.config.tsSupported route files:
page.tsxlayout.tsxloading.tsxerror.tsxnot-found.tsxroute.ts- optional
actions.ts
Marks a client boundary. The compiler moves that subtree into the browser graph, emits client references for RSC decoding, and prevents direct imports of server-only modules from that subtree.
Supported today for file-level async exports. The compiler emits an action manifest and client stubs that call POST /_reora/actions.
Native HTML form posts are also supported at the endpoint level by sending:
_actionorid_csrf- optional
args
Supported for file-level and inline cacheable async exports. The server transform wraps those exports with the cache runtime and keys entries by function id plus serialized args.
packages/compiler performs:
- route and module scanning
- graph splitting for server and client boundaries
- source transforms for client references, action stubs, and cache wrappers
- generated source emission into
.reora/cache/generated/<buildId> - Bun browser bundling into
dist/client - manifest emission into
dist/manifests
packages/runtime performs:
- HTML document rendering
- Flight endpoint rendering
- action execution with CSRF and same-origin checks
- request memoization and process cache access
- static asset serving
- development rebuilds with SSE live reload
Build artifacts are written to:
dist/
client/
manifests/
styles/
.reora/
cache/
entries/
generated/<buildId>/Important manifests:
dist/manifests/routes.jsondist/manifests/actions.jsondist/manifests/cache.jsondist/manifests/client.jsondist/manifests/runtime.json
Development mode now keeps generated source trees versioned by build id, so Bun does not keep serving stale route, RSC, or action modules after a rebuild. The dev server exposes /_reora/live as an SSE stream and the browser runtime reloads when a new build id is published.
Production mode serves only prebuilt artifacts. It does not rebuild on requests.
The custom protocol is intentionally narrow. It currently supports:
- plain objects
- arrays
- strings, numbers, booleans,
null,undefined - React elements
- client references
- Suspense boundaries
It intentionally rejects unsupported values such as Date, Map, class instances, and other non-plain objects. That contract is enforced in tests so protocol behavior fails explicitly instead of silently degrading.
The framework is stable enough for local development and iteration, but it is still a prototype. The current test suite covers:
- directive scanning and graph splitting
- cache wrapping and invalidation
- protocol roundtrips and unsupported-value rejection
- artifact-backed production startup
- native form action CSRF handling
- development rebuild freshness and live reload signaling
Known limitations:
- no inline server actions yet
- no durable remote cache adapter yet
- no official
react-server-dom-webpacktransport - live reload is full-page reload, not Fast Refresh