I just published effective-rsc 0.1.0.
React owns the UI. Effect owns the runtime.
Back in 2023, the mental model behind React Server Components immediately clicked with me. I ended up building cosmos-rsc and started writing a series about building an RSC framework. The series stopped at part two, but my interest in RSC never did.
I had a similar reaction when I finally gave Effect a serious try. Effect gives the backend one model for services, errors, concurrency, cancellation, and resource lifetimes. This is especially useful when working with coding agents: there are fewer disconnected conventions for either the human or the agent to rediscover in every codebase.
So I combined the tools I wanted to use:
- React Server Components for the application model
- Effect for the runtime
- Rspack for its native RSC integration
- Bun as the server runtime
- The Navigation API for client navigation
That became effective-rsc.
By the time this showed up in my feed, I was already deep into building it. Good advice. Slightly late.
What it looks like
Pages are Effects with Schema-decoded route parameters. Routes and application services close at one composition point, and Server Functions use the same runtime while preserving React's protocol:
import { Effect, Schema } from 'effect';
import { ERSC } from './ersc';
import { RootLayout } from './root-layout';
import { Bookmarks } from './services/bookmarks';
const BookmarkPage = ERSC.Page.make({
params: Schema.Struct({ bookmarkId: Schema.NonEmptyString }),
render: Effect.fn('BookmarkPage')(function* ({ params }) {
const bookmarks = yield* Bookmarks;
const bookmark = yield* bookmarks.get(params.bookmarkId);
return <h1>{bookmark.title}</h1>;
}),
});
export default ERSC.make({
routes: ERSC.Routes.make({ layout: RootLayout }).page('/bookmarks/:bookmarkId', BookmarkPage),
layer: Bookmarks.layer,
});
Instead of awaiting work inside a Server Component, you can yield* it. Service requirements stay
visible in the type, one application Layer provides the implementations, and the work stays
attached to the request scope.
If a request is aborted, its Effect work is interrupted and its resources are cleaned up. Server
Functions run as Effects with Schema-validated input while continuing to use React's native
"use server" protocol.
If you already understand Effect and RSC, most of effective-rsc should feel familiar.
The repository includes a complete event platform that exercises nested routes, scoped middleware, Server Functions, Effect SQL, and View Transitions.
The client router
The part I am most opinionated about is the client router.
It is built directly on the browser Navigation API. Navigation settles when the destination reaches its first UI commit instead of waiting for the complete Flight stream. This keeps the URL, UI, Suspense, scroll, focus, and View Transitions coordinated while unfinished work continues streaming from the server.
Events
Upcoming
Effect Days
September 18
There is no History API compatibility layer. If a browser lacks the Navigation API or
NavigationPrecommitController, ERSC skips hydration. Links and native forms continue as a normal
multi-page application, but Client Components are not interactive.
That constraint let me build the router around the browser primitive I wanted instead of carrying an older navigation model into a new framework.
Try it
bunx create-ersc-app my-effective-rsc-app
cd my-effective-rsc-app
bun run dev
The package includes a combined
LLMS.md
reference that an agent can read before touching an application.
Or paste this into a coding agent:
Create a small bookmark manager with effective-rsc.
Start with:
bunx create-ersc-app effective-bookmarks
It should let me save bookmarks, list them, and open a page for each bookmark.
About 0.1.0
This is an experimental first release. It currently uses React Canary, Effect v4 RC, TypeScript 7, Rspack's RSC implementation, and modern browser APIs. Bun is the only supported server runtime.
Credits
effective-rsc exists because of the work already done across React, Effect, Bun, and Rspack.
Rspack and
react-server-dom-rspack provide the
native RSC compilation and transport. Special thanks to
Cong-Cong Pan for their work on Rspack's RSC implementation.
The framework also learned from:
- rsc-html-stream by Devon Govett
- Waku by Daishi Kato
- Twofold by Ryan Toronto
- Next.js, Vite RSC,
rspack-rsc, andrsbuild-plugin-rsc
Links
0.1.0 is available now. Try it and tell me where the model falls short.