FluxyChat

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-room

Pass 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 whiteboard

Strokes 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.

On this page