Built into RedwoodSDK

Hook, line, and sync

useSyncedState is a drop-in replacement for useState that synchronizes state across every connected client, instantly.

-const [count, setCount] = useState(0);
+const [count, setCount] = useSyncedState(0, "counter");

Plant a forest. One click at a time.

Every tree is procedurally generated (unique 8-bit pixel art, no two alike.) Plant as many as you want. Together, we grow a forest, synced across every browser, instantly.

Redwood Forest
๐ŸŒฒ 2 trees available to plant
LIVE
Click a slot to plant your first redwood ๐ŸŒฒ

Every tree is procedurally unique ยท Click trees to grow them ยท Synced via useSyncedState

Open this page in another tab. Plant a tree there. See it appear here. Every tree is unique. useSyncedState in action.

This is all it takes.

No WebSocket handlers. No pub/sub. No third-party service. Just React, Cloudflare, and one hook.

1. Your Component
// That's it. Really.
const [count, setCount] = 
  useSyncedState(0, "counter");
2. Worker Routes
export { SyncedStateServer };

export default defineApp([
  ...syncedStateRoutes(
    () => env.SYNCED_STATE
  ),
]);
3. Wrangler Config
// wrangler.jsonc
"durable_objects": {
  "bindings": [{
    "name": "SYNCED_STATE",
    "class_name": "SyncedStateServer"
  }]
}

Security? The client doesn't decide.
The server does.

Your frontend is intentionally user-agnostic. Server-side key handlers and room handlers enforce isolation โ€” with full access to your auth context. The client never sees the scoping logic.

Frontend ยท User-agnostic
// Component just says 'private'
const [notes, setNotes] =
  useSyncedState("", "notes", "private");

The component doesn't know who the user is. It just requests a "private" room.

Server ยท Enforces Access
// Server knows what 'private' means
registerRoomHandler((roomId) => {
  if (roomId === "private")
    return `user:${userId}`;
});

The server transforms "private" โ†’ "user:abc123". Each user gets their own isolated state โ€” enforced on the server.

Rooms aren't just for grouping โ€” they're a security boundary. Key handlers and room handlers run on the server, with full access to your auth context.

Powered by Cloudflare
and the Web.

Your server is the source of truth. Cloudflare Durable Objects handle coordination, persistence, and global distribution. You write React.

1

Client calls setState

Your React component calls setCount(c => c + 1). Standard React. Nothing unusual.

2

Durable Object syncs

A Cloudflare Durable Object receives the update, stores it as the source of truth, and broadcasts to all connected WebSockets.

3

Every client updates

All connected clients receive the new state via standard WebSockets. React re-renders. Instantly.

What will you build?

You can build all kinds of live experiences. Anything where data should update instantly for everyone.

Start building for real this time

Scaffold a project and start syncing state in under a minute.

$npx create-rwsdk my-project
Read the docsโ†’

A simple framework for humans. Server-first React, running on the Cloudflare platform. Simple to build. Easy to maintain. RedwoodSDK begins as a Vite plugin that unlocks SSR, React Server Components, Server Functions, and realtime features. Its standards-based router, with support for middleware and interruptors, gives you fine-grained control over every request and response. With built-in access to Cloudflare Workers, D1 (Database), R2 (Storage), Queues, AI, and full local emulation via Miniflare, development feels just like production.

Copyright ยฉ 2026 RedwoodJS Inc. All rights reserved.