Skip to content

A host can hold more than one document. A chat keeps one per message. A game keeps one per player. Each client gets the ones it asks for, and patches for those only. A long thread stays fast on a phone that follows the last fifty messages, not all ten thousand.

Some documents live only as long as one connection: a cursor, a selection, a viewport. They go away when the client does.

A host holds a main room document and three player documents. Client A receives the room document and the players Ada and Lin. Client B follows only Kai and receives that player document.Hostroommain documentplayer · adaplayer · linplayer · kaiClient Anear Ada and LinClient Bnear Kairoomlinkaiada

Keyed documents belong to a protocol both sides register. The host mounts one per key; a command adds it to its caller with this.attach.include and takes it away with exclude. this.attach.mount adds one that lives only as long as the connection.

const host = getStateHost(state)!;
host.mount("player", { x: 0, y: 0 }, { key: ["ada"] });

const commands = useStatewireCommands({
  follow(player: string) {
    this.attach.include("player", [player]);
  },
});

Filters

Two people can attach to the same document and see different things. A read filter runs once per client and document, and redacts what that client receives. An owner sees the model's reasoning; a viewer gets null in its place.

  • Rules: keep, null, pick fields or omit fields.
  • Clients that share a filter share its work: it runs once per update for all of them.
  • Filters cover snapshots and patches. Command results are sent to their caller unfiltered.
  • When a role changes, reconnect that client and the new filter applies.