Yjs Storage

pluv.io supports conflict-free replicated data-types (CRDT) storage with yjs. This allows modifying shared data between multiple users, and also leveraging the yjs ecosystem such as rich-text-editor bindings.

Set initialStorage

To get started with yjs for pluv.io, first set an initialStorage config on your createRoomBundle config.

1import { yjs } from "@pluv/crdt-yjs";
2import { createBundle, createClient } from "@pluv/react";
3import type { AppPluvIO } from "backend/io";
4
5const client = createClient<AppPluvIO>({
6 wsEndpoint: (room) => `${process.env.WS_ENDPOINT}/api/room/${room}`,
7});
8
9const { createRoomBundle } = createBundle(client);
10
11export const pluvRoom = createRoomBundle({
12 // Set the initial storage value, and type here
13 // Don't worry, we can set a different default value in the room component
14 initialStorage: yjs.doc(() => ({
15 messages: yjs.array(["hello world!"]),
16 })),
17});

Setup PluvRoomProvider

Then, setup PluvRoomProvider with your new initialStorage if it is different than your default set from createRoomBundle.

1import { yjs } from "@pluv/crdt-yjs";
2import type { FC } from "react";
3import { pluvRoom } from "frontend/io";
4
5export const MyPage: FC = () => {
6 return (
7 <pluvRoom.PluvRoomProvider
8 room="my-room-id"
9 initialStorage={() => ({
10 messages: yjs.array(),
11 })}
12 >
13 <MyRoom />
14 </pluvRoom.PluvRoomProvider>
15 );
16};

Use yjs shared-types

We can then use yjs shared-types to leverage shared CRDTs between connected clients using useStorage.

1import { pluvRoom } from "frontend/io";
2import { useCallback } from "react";
3
4// "messages" is a key from the root properties of `initialStorage`.
5const [messages, sharedType] = pluvRoom.useStorage("messages");
6
7const addMessage = useCallback((message: string) => {
8 sharedType?.push(message);
9});
10
11messages?.map((message, i) => <div key={i}>{message}</div>)