Presence, live cursors and CRDT storage over one WebSocket. 41 React hooks, and a server you run yourself.
bun add @waits/lively-reactimport { RoomProvider, useOthers } from "@waits/lively-react";function Canvas() { const others = useOthers(); return <CursorOverlay peers={others} />;}<RoomProvider roomId="board-1" initialStorage={{ shapes: [] }}> <Canvas /></RoomProvider>The previews below are scripted so they behave the same every time. The six links further down are the real thing, running on the same server.
const others = useOthers();
const [, update] = useMyPresence();
function onPointerMove(e) {
update({ cursor: { x: e.clientX, y: e.clientY } });
}const todos = useStorage((root) => root.get("todos"));
const addTodo = useMutation(({ storage }, text) => {
storage.root.get("todos").push({ text, done: false });
}, []);All six run against the same server, and their source is in the repository under examples/.
One command starts it. No account, no dashboard, no egress bill.