Skip to content

Your state lives in one place: the host. Every client that attaches gets a live copy. A browser tab, a phone and a Python script all see the same thing at the same time, with no sync code of your own.

A client gets a snapshot when it attaches, then each change as a small patch. A streaming reply sends only the characters it adds. A client that drops and comes back starts from a fresh snapshot, so it shows what happened while it was away.

One host and three clients. The host owns the state. A browser tab, a phone and a server script each attach to it, receive a snapshot, then receive patches as the state changes.Hostowns the stateBrowser tablive copyPhonelive copyServer scriptlive copypatchespatchessnapshot, then patches

The host

State is plain data: objects, arrays, strings, numbers, booleans and dates. Change it like any object. Statewire records each write and sends it out.

The client

One hook in React. The same client attaches to JavaScript and Python hosts.

import { StatewireHttp, useStatewire } from "statewire";

const { state, commands, connection } = useStatewire<
  { messages: string[] } | undefined,
  { say(text: string): void }
>({
  transport: StatewireHttp({ url: "/rooms/lobby" }),
});

state re-renders on every patch. connection.status says whether the copy is live.

What travels

A patch is a list of add, replace and remove operations on paths. From {"score":0,"players":["Ada"],"text":"Hi"}:

[
  {"op":"replace","path":["score"],"value":1},
  {"op":"add","path":["players",1],"value":"Lin"},
  {"op":"add","path":["text",2],"value":"!"}
]

The last one appends ! to text. That is how a streaming reply costs a few bytes per token. The format is Statepatch; the values are a Statewire Document.