useSyncedState is a drop-in replacement for useState that synchronizes state across every connected client, instantly.
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.
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.
No WebSocket handlers. No pub/sub. No third-party service. Just React, Cloudflare, and one hook.
// That's it. Really.
const [count, setCount] =
useSyncedState(0, "counter");export { SyncedStateServer };
export default defineApp([
...syncedStateRoutes(
() => env.SYNCED_STATE
),
]);// wrangler.jsonc
"durable_objects": {
"bindings": [{
"name": "SYNCED_STATE",
"class_name": "SyncedStateServer"
}]
}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.
// 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 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.
Your server is the source of truth. Cloudflare Durable Objects handle coordination, persistence, and global distribution. You write React.
Your React component calls setCount(c => c + 1). Standard React. Nothing unusual.
A Cloudflare Durable Object receives the update, stores it as the source of truth, and broadcasts to all connected WebSockets.
All connected clients receive the new state via standard WebSockets. React re-renders. Instantly.
You can build all kinds of live experiences. Anything where data should update instantly for everyone.
Scaffold a project and start syncing state in under a minute.