Core SDK
Storage (Yjs)
Synced CRDT room state. useStorage wrapping Y.Map, LiveFile refs, Tiptap.
Storage is the document: Yjs on the room Durable Object (yjs-sync.js). Do not invent a second CRDT. Presence is "now"; chat is the timeline; this is the file.
Import from @fluxy-chat/sdk/yjs (or @fluxy-chat/react/yjs) so chat-only clients skip the yjs graph.
React
import {
FluxyYjsProvider,
useStorage,
useMutation,
useUndo,
useRedo,
useYjsDoc,
uploadLiveFile,
} from "@fluxy-chat/sdk/yjs";
<FluxyYjsProvider workerUrl token={jwt} roomId>
<Board />
</FluxyYjsProvider>Prefer nesting inside FluxyRealtimeProvider so you do not pass token twice. Standalone, authTokenProvider is accepted as an alias of token. userId is optional when the JWT has sub.
const title = useStorage((root) => String(root.title ?? ""));
const setTitle = useMutation((storage, next: string) => {
storage.set("title", next);
}, []);useStorage reads a JSON snapshot of the storage Y.Map. useMutation writes that map inside a Yjs transaction. Undo/redo is Y.UndoManager on the map + Tiptap fragment (prosemirror).
The provider opens a binary WebSocket on the same /ws/room/:id (replay off). Chat useChat stays JSON on its own socket. Same room DO, same persistence key.
LiveFile
Bytes go through existing POST /upload (client.uploadFile). Put a JSON ref on the CRDT, not a second blob store:
const live = await uploadLiveFile(client, roomId, file);
storage.set("hero", live); // { liveFile: true, id, name, mime, size, url }Tiptap
npx @fluxy-chat/create-fluxy-chat@latest my-doc --example tiptap-roomPass useYjsDoc() into @tiptap/extension-collaboration with field: "prosemirror". Disable StarterKit history; undo is Yjs.
Lexical / BlockNote / CodeMirror wait until this example is copy-pasteable.
Whiteboard
npx @fluxy-chat/create-fluxy-chat@latest my-board --example whiteboardStrokes live on Y.Array inside Y.Map("storage") (storage.set("strokes", new Y.Array())). Cursors stay on useChat().sendCursor. Same room DO. The dashboard can render that doc with Excalidraw in the browser. Excalidraw is not a second backend.