rect.sh

State & syncing

The store, optimistic writes, and revisioned JSON Patch deltas.

connect() returns a store over your view model. Reads are synchronous; writes apply optimistically and sync to the host.

import { connect } from '@rectsh/rect';

const rect = await connect();

Reading

rect.get(); // the whole view model
rect.get('items.0.done'); // a dot path — numeric segments index arrays
rect.subscribe((state) => render(state)); // fires on connect + every change
rect.revision; // optimistic-concurrency token (a number)

subscribe returns an unsubscribe function. In React you never call these directly — the hooks do (see React).

Writing

Three write ops, all of which apply locally at once (optimistic), then sync:

rect.set('title', 'Hi'); // set one path
rect.update((draft) => draft.items.push(x)); // mutate a draft
rect.patch({ completion: { approved: true } }); // shallow merge

How syncing works

  1. A write mutates a local copy immediately, so the UI updates with no round trip.
  2. The store diffs the change into an RFC 7386 JSON Merge Patch and sends it to the host.
  3. The host applies the patch to the authoritative store, bumps the revision, and returns only the committed RFC 6902 JSON Patch operations.
  4. The store folds that delta into its authoritative state and rebases any still-unsynced local edits on top.

The same channel delivers changes made by someone else — most importantly an agent calling rect_patch or rect_dispatch. Those arrive as revisioned deltas and your subscribers fire, so the view stays live without polling. A full snapshot is fetched only on initial connection or when a missed revision requires recovery.

Named actions use the same model with an additional optimistic queue. The SDK runs the compiled action handler in the view immediately, sends its fixed actionId, now, and seed to the host, and normally receives only a revision ack. The authoritative state advances in ack order, with any still-pending actions replayed on top. A rejection, timeout, revision gap, or Realtime reconnect triggers /check, then pending actions are replayed over that fresh snapshot.

Write and delta semantics

Manual patch() writes remain JSON Merge Patch: objects deep-merge, null deletes a key, and arrays replace wholesale in the request. Committed responses and Realtime broadcasts use JSON Patch operations, so changing one array item can return a path such as { "op": "replace", "path": "/items/0/done", "value": true } instead of retransmitting the array.

On this page