Family using RedwoodSDK application

This could be the start of something small

RedwoodSDK is a React framework for building server-side web apps on Cloudflare

From concept to cloud

It begins as a Vite plugin that unlocks SSR, React Server Components, Server Functions, and realtime features.And it ends with you building something awesome!

$ npx degit redwoodjs/sdk/starters/standard

One Response to build them all

Every route is just a function

  • Return JSX, stream a response, or upgrade to websockets.
  • There’s no special syntax or compiler magic.
  • A route is a standard function that takes a Request and returns a Response - or even a <Page />
export default defineApp([
render(Document, [
index(Home), // JSX page
route("/users", UsersPage), // JSX page
route("ping", () => new Response(
"pong", { status: 200 }
)),
]),
]);

Built on Standards

  • Request and Response follow the native Web API.
  • Stream responses, upgrade protocols, debug in DevTools — no wrappers or black boxes.
defineApp([
route("/upload/", async ({ request }) => {
const formData = await request.formData();
const file = formData.get("file") as File;
// Stream the file directly to R2
const r2ObjectKey = `/storage/${file.name}`;
await env.R2.put(r2ObjectKey, file.stream(), {
httpMetadata: {
contentType: file.type,
},
});
return new Response(JSON.stringify({ key: r2ObjectKey }), {
status: 200,
headers: {
"Content-Type": "application/json",
},
});
}),
]);

Co-Locate Logic and UI

  • Define your API and UI in the same place.
  • Keep your JSON and JSX responses together, scoped to a single router.
  • One file, one mental model.
const authRoutes = [
route("/login", Login),
route("/account", [
async ({ ctx, request }) => {
if (!ctx.user) {
const headers = new Headers();
await sessions.remove(request, headers);
headers.set("Location", "/auth/login");
return new Response(null, {
status: 302,
headers,
});
}
},
AccountPage
]),
];
export default authRoutes;

Interruptors

  • Shape the request flow before it hits your route.
  • Interruptors let you intercept requests, check auth, redirect, or halt the response, on a per route basis, with full access to the environment and context.
function isAuthenticated({ request, ctx }) {
// Ensure that this user is authenticated
if (!ctx.user) {
return new Response("Unauthorized", { status: 401 })
}
}
defineApp([
route("/blog/:slug/edit", [isAuthenticated, EditBlogPage]);
// EditBlogPage will only run if isAuthenticated = true
])

Middleware That Matters

  • Run logic before and after your routes.
  • Middleware is part of the request/response flow — ideal for injecting headers, setting up context, or streaming from the edge.
defineApp([
sessionMiddleware,
async function getUserMiddleware({ request, ctx }) {
if (ctx.session.userId) {
ctx.user = await db.user.find({ where: { id: ctx.session.userId } });
}
},
route("/hello", [
function ({ ctx }) {
if (!ctx.user) {
return new Response("Unauthorized", { status: 401 });
}
},
function ({ ctx }) {
return new Response(`Hello ${ctx.user.username}!`);
},
]),
]);

Total Control Over the Document

  • Render the HTML document yourself — no hidden magic.
  • You choose what goes over the wire. Turn client-side React on or off.
  • Inject headers, preload tags, inline styles, or raw HTML.
  • You’re in control of the entire response, from status code to closing tag.
import { Document } from "@/pages/Document";
import { NoJSDocument } from "@/pages/NoJSDocument";
import { HomePage } from "@/pages/HomePage";
export default defineApp([
render(Document, [route("/", HomePage)]),
render(NoJSDocument, [
route("/no-js", () => new Response(
"No Javascript injected in this Document, just plain HTML",
{ status: 200 })
)
])
]);

React Server Components - as they're meant to be

React Server Components are a powerful way to build server-side web apps on Cloudflare.

Everything is server-first by default. Your components run on the server where they belong, streaming HTML straight to the browser. When you need interactivity, just mark a component with use client. It's the same mental model you'd use anywhere else—only now it runs on the edge.

There's no need to wrestle with bundlers, patch frameworks, or manually split code between server and client. RedwoodSDK treats React's directives as first-class citizens and integrates them seamlessly with Vite and Cloudflare Workers. The result is lightning-fast time-to-interactive, zero boilerplate, and a dev environment that mirrors production—without any extra setup.

Concept to Cloudflare

RedwoodSDK is built for Cloudflare from the first line of code.

No adapters, no shims. What runs locally is what runs in production. Development uses Miniflare to emulate Cloudflare Workers with uncanny accuracy. You're not faking the edge. You're building on it. No config drift. No "it worked on my machine." Just a clean path from idea to deploy.

PS… Built for Builders

RedwoodSDK is for people who write software they own.

It's built on browser standards, not vendor abstractions—just native Web APIs and predictable behavior from request to response.

Bring your own tools. Use realtime out of the box. Run locally on Cloudflare's stack with zero config—D1, R2, Queues, Workers AI, and more.

No wrappers.No black boxes.Just flow.

Be the first to know

Get a summary of what we've shipped, articles we've written, and upcoming events straight to your inbox, at most once every two weeks.

logo