The next web is
High-performance sync for multiplayer web apps
Why Reflect?
Absurdly Smooth Motion
Throw away your interpolation code. Reflect syncs changes at 120 FPS (hardware permitting). Built-in batching and buffering provide buttery smooth, precision playback automatically — across town or across the globe.
Transactional Conflict Resolution
CRDTs converge, but to what?? Validation and custom business logic aren't possible.
Reflect uses a more powerful technique known as Server Reconciliation. Your mutation code runs server-side and is authoritative. Clients are guaranteed to converge with server changes.
Mutators can enforce arbitrary business logic, fine-grained authorization, server-side integrations, and more.
First-Class Text
Your may have heard that multiplayer text is hard. No worries. Reflect has built-in, high-quality text support via the industry standard yjs library.
Automatic Persistence
There's no separate, slower persistence API to juggle. Write changes as they happen (yes, every mouse movement) and they are stored continuously and automatically, up to 50MB/room.
Local-First
Set clientPersistence: true
and data is also stored on the client, providing instant (“local-first”) startup, navigation, and offline support.
On-“Prem” Available
Use Reflect as a traditional SaaS, or deploy it to your own Cloudflare account.
We'll run, monitor, and update it. You maintain control, ownership, and business continuity with a perpetual source license.
How it Works
Step 1: Create Room
Users connected to the same room see each others' changes in realtime.
1import {Reflect} from "@rocicorp/reflect";
2
3const reflect = new Reflect({
4 reflectAPIKey,
5 roomID: "myFirstRoom",
6});
7
8reflect.onConnect(({roomID}) => {
9 console.log(`Connected to room ${roomID}`);
10});
Step 2: Define Mutators
Mutators are how you make changes to rooms. They are JavaScript functions you define, that run on both the client and the server.
By replaying mutators on the server, Reflect naturally resolves many types of conflicts, while allowing for custom, authoritative server logic.
Try it: Use the demo below to increment a multiplayer counter. Increase the latency and quickly increment on both clients. Notice how normal arithmetic logic naturally sums concurrent operations, without the need for CRDTs.
1export default {
2 async increment(tx, args: {key: string, delta: number}) {
3 const {key, delta} = args;
4 const prev = await tx.get(key, 0);
5 const next = prev + delta;
6 console.log(`Running mutation ${tx.clientID}@${tx.mutationID} ` +
7 `on ${tx.environment}: ${prev} → ${next}`);
8 await tx.put(key, next);
9 },
10}
Client 1
Console
Server Console
Client 2
Console
Step 3: Render Reactively
Subscribe to changes in Reflect and render your UI reactively. There's no need to interpolate. You receive updates at up to 120 fps, just as if the collaborator was local.
Try it: Notice how even when the latency is high, changes playback on the receiver exactly as they happened on the source.
1import {Reflect} from "@rocicorp/reflect";
2import mutators from "./mutators";
3const authToken = "$your-auth-token";
4const roomID = "myFirstRoom";
5
6const r = new Reflect({
7 reflectKey,
8 authToken,
9 roomID,
10 mutators,
11});
12
13r.subscribe(tx => tx.get("degree"), val => {
14 console.log(`Key "degree" changed to: ${val}`);
15 document.querySelector("#degreeImage").rotation = val;
16});
17
18<Slider onChange={(val) => reflect.mutate.setDegree(val)} \>
Client 1
Console
Server Console
Client 2
Console
You're Done.
Reflect publishes your mutators to a unique sandboxed environment. Rooms are backed by Cloudflare's Durable Object technology and scale horizontally by room.
Shell
>reflect publish
🎉 Published! Running at https://myapp.reflect.net/.
Simple, Usage-Based Pricing
We charge by monthly active hours. A room is active when it has one or more connected users. Background tabs disconnect automatically.
Examples
- Bob is in room
giraffe
from 9am to 11am. Sally joinsgiraffe
at 10am and stays until 12:30pm. That's 3.5 room hours (9am – 12:30pm). - Same as above, but James is concurrently in room
platypus
from 10am to 12pm. That's an additional 2 hours for a total of 5.5.
Coming Soon, from Rocicorp
Reflect is being built by the team behind Replicache, and we're working toward a public beta later this year.
Want to be first to try it? Let us know what you're building and how you'd use Reflect. We'll get you access as soon as we can.
You can also contact us by email, on Twitter, or on Discord.
Early Reactions

