Yjs for collaborative Jupyter notebook whiteboards

I wanted to share a project I’ve been working on that uses Yjs to turn Jupyter notebooks into collaborative whiteboards. A notebook file is something that data scientists and other researchers use to record the steps for data preprocessing and model building, so there’s a sequence of cells in it containing code, plots, tables, markdown with Latex equations, etc. People will screen-share these notebooks running in the Jupyter web app either over Zoom or in-person in a conference room, but then there’s no way for others in the meeting to interact with the notebook.

My project is JupyterSpot which uses a drawing app (tldraw) overlaid on top of an HTML rendering of the notebook file (rendered with nbviewer). Tldraw lets you have live cursors, freehand drawings, text, and sticky notes. This makes it super easy for someone to point to the region of the plot that they’re talking about.

For syncing the tldraw state between meeting participants, I chose Yjs since I was first introduced to it through the Jupyter project where it’s utilized for collaborative editing. I was more concerned with viewing notebooks than editing and just wanted to quickly take my notebook that’s either running locally or firewalled behind some corporate network and turn it into a shareable URL.

The notebook files are usually pretty long, and there’a a lot of verbal “can you scroll up a little, no that’s too far, back down some” during screen shares when someone has a question about something that the presenter has scrolled past. I added each participants scroll position to their awareness, then added a shared Y.Map with a scroll leader key. The current scroll leader’s client ID is written to that key’s value so that anyone in the meeting can request to become the scroll leader and have all of the other participants sync to their scroll position.

On the backend I’m using y-websocket with LevelDB persistence, and it’s worked great so far. Thanks @dmonad for creating a great project and answering my questions on Gitter. The sponsorware model is really inspiring, and tldraw was also created with that same model. I may end up going that route on day since I quit my data scientist job, but I’d already spent too much time figuring out Stripe for this project. In any case, I make sure to sponsor you guys if I use something you built.

It’d be cool if you could add JupyterSpot to this page: Yjs in the Wild - Yjs Docs. I give a shout out to Yjs on the home page for JupyterSpot: https://jupyterspot.com, and there’s some demo videos there for anyone who is interested.


This is great, thanks so much for sharing!

I really like the idea with the shared scrollarea (if you can turn it off).

It’s too bad that we couldn’t finish the collab feature. The main parts are there for others to reuse. I’m really glad that you built on top of this!

Sure, gonna add you to the Yjs in the Wild section :slight_smile:

Thanks Kevin!

Yeah there’s a button to toggle the scroll syncing on and off, and it’s off by default since there was some confusion why you couldn’t scroll when someone else was the leader.

I’ll probably add the scroll syncing part to JupyterLab proper since everything is already setup for it. I know there a few bugs in RTC editing that they’re in the process of ironing out for the next release. I think there’s a lot of interesting things you could do with the Yjs revision history data that you get from editing notebooks in RTC mode with JupyterLab. One is sorting notebook cells by their editing dwell time. I know I usually spend the most time in just a few cells in a given notebook, usually to make a plot look just right, so being able to automatically summarize the most important cells in a set of notebooks using the y-websocket data is definitely something I want to try out.

1 Like