Hey i have seen the work done by Yussef “Matrix-CRDT: Yjs provider that connects to Matrix”
I wanted to do the same thing but my project is closed source for now so i didn’t look at the code because of the license
insted Timo made a demo that is MIT licensed
toger5/matrixRTC-example
he talked about here too
" FOSDEM25 – MatrixRTC: Building Real-Time Applications on Matrix" at (14:19)
So i built this app using the MatrixRTC example
Matrix Notebook
i save the state of the doc as a state event in the matrix room every 5 mins and i use the device id so only one state in room per device exist and only the device will be able too override their own state
const update = Y.encodeStateAsUpdate(ydoc);
const updateString = btoa(String.fromCharCode(...update));
await matrixClient.sendStateEvent(
room_id,
"yjs.doc." + matrixClient.getDeviceId()!,
{
type: "update",
doc: updateString,
},
matrixClient.getUserId()!
);
then at the start of the app i get the state events and apply them
const stateEvents = await matrixClient.roomState(room_id);
const yjsEvents = stateEvents.filter((event) =>
event.type.startsWith("yjs.doc.")
);
yjsEvents.forEach((event) => {
const binaryString = atob(event.content.doc);
const update = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
update[i] = binaryString.charCodeAt(i);
}
Y.applyUpdate(ydoc, update, "remote");
});
also MatrixRTC uses Livekit which is a scalable way to do webrtc …it will make a livekit room and then you can use it send doc updates and awareness updates between clients
const livekitRoom = new Room({});
livekitRoom.connect(sfuConfig.url, sfuConfig.jwt);
livekitRoom.on("connected", () => {
const update = Y.encodeStateAsUpdate(ydoc);
const updateString = btoa(String.fromCharCode(...update));
let update_json = JSON.stringify({
type: "update",
doc: updateString,
});
const update_encoder = new TextEncoder();
const update_data = update_encoder.encode(update_json);
livekitRoom.localParticipant.publishData(update_data, {
reliable: false,
});
ydoc.on("update", async (u, origin) => {
const update = Y.encodeStateAsUpdate(ydoc);
const updateString = btoa(String.fromCharCode(...update));
let json = JSON.stringify({
type: "update",
doc: updateString,
});
const encoder = new TextEncoder();
const data = encoder.encode(json);
livekitRoom.localParticipant.publishData(data, {
reliable: false,
});
});
just wanted to showcase it here in case anyone was intrested in this