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

Setup PluvRoomProvider

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

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

Use yjs shared-types

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

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