« BackLearn Yjs Interactivelylearn.yjs.devSubmitted by paulgb 21 hours ago
  • jakelazaroff 21 hours ago

    Hey HN! I'm the developer at Jamsocket who made this. In case you're not familiar with Yjs, it's a CRDT library for building collaborative and local-first apps.

    The thing is, if you're not used to working with distributed state there's definitely a learning curve. Even simple things like incrementing a counter — the "hello world" of JavaScript framework demos — get tricky when dealing with multiple clients. Worse, a lot of tutorials are just like "install this library and text editor integration and boom you have an app", which doesn't give you a good mental model for what's actually happening.

    So we made Learn Yjs! It's an interactive Yjs tutorial. I wanted it to be really intuitive for people just getting their feet wet with local-first development, so there are lots of explorable demos and coding exercises. The idea is to use interactive examples to build an understanding from the ground up.

    Hope you like it :)

    • KaiMagnus 12 hours ago

      > "install this library and text editor integration and boom you have an app", which doesn't give you a good mental model for what's actually happening.

      I was interested in working with CRDTs and collaboration in general for a while now and this has been the biggest issue whenever I tried to get into it. Websockets also seem a bit harder to find (free) hosting for.

      Btw, your other tutorials on CRDTs were also a great help.

      • jakelazaroff 3 hours ago

        Thank you!

        As far as websocket hosting, there are a few services out there. We offer a pretty generous free tier for Y-Sweet [1] with 10GB of storage. There's also PartyKit and Liveblocks, though I'm not sure what their pricing is like.

        [1] https://jamsocket.com/y-sweet#y-sweet-pricing

        • Imustaskforhelp 3 hours ago

          Cloudflare workers can host soketi which is websocket.

        • santa_boy 17 hours ago

          I am just looking at this but quick question. Is there an example for building a local-first app? Also, I working with plain vanilla HTML & JS and Alpine. Can this be used in my apps?

          • paulgb 13 hours ago

            Y-sweet (which this is built with) allows you to make a Yjs app local-first by passing “offlineSupport” to the provider when constructing.

            There’s a demo of this here: https://demos.y-sweet.dev/color-grid

            The source for that demo is here: https://github.com/jamsocket/y-sweet/blob/5fa6941cf5568f4a3f...

            That demo uses react, but there is a vanilla js version of the same demo here: https://github.com/jamsocket/y-sweet/tree/main/examples/vani...

            (The vanilla js version is not local first, but it would just be a matter of passing the same offlineSupport flag to make it so.)

            • steve_adams_86 an hour ago

              I just noticed that if you install the example service after setting up an account, it installs a version of @y-sweet/react which doesn't offer the offlineSupport prop.

              The version specified is ^0.5.1. After switching to 0.7.1 as the repo you linked uses, all is well. Probably not a big deal for most newcomers, but it might be worth updating dependencies in the example service.

              • paulgb 44 minutes ago

                Thanks Steve, good catch!

              • santa_boy 13 hours ago

                Thank you. This is the direction I needed. Will try out

            • adeptima 12 hours ago

              Thank you. Keep going. Very good topic to expand

              • nhatcher 19 hours ago

                Woah! Beautifully done! I wonder if I will finally understand CRDT with this. Will go through it over the weekend.

                Congratulations!

              • patwolf 5 hours ago

                I'm currently using Yjs to build an app that needs to work offline. It's not actually a real-time or collaborative app. However, if you think of the server as being one collaborator and the app being another, then it's easy to imagine use cases for it.

                • adeptima 12 hours ago

                  Yjs is nice. Easy to get p2p results.

                  Yjs backend, its persistence, eventual conflict resolution (one of editors stayed too long offline), history rewind seems like a tough engineering challenge to crack.

                  Always wanted to have a nice experience with block editor like Platejs https://platejs.org/

                  There are nice attempts simplify dev experience with solutions like Liveblocks https://liveblocks.io/text-editor However most options come at the expense of controlling your data.

                  CRDT keyword search on HN bring consistently good results and interest in the topic, but no good options on open source backend side. Checked it many times in the past. Please correct me if I missed something.

                  https://hn.algolia.com/?dateRange=pastYear&page=0&prefix=tru...

                  Most people expectations it should work at least as in Google Docs or Notion, and on the dev side it should be store privately in Postgres JSONB like format without going deep into details.

                  • blixt 12 hours ago

                    I agree. In theory you need to just distribute serialized patches but in a real world backend scenario you may need to integrate with knowledge of current document state, user identity, and possibly even some level of access control.

                    I’ve wanted to use Y.js with a Go backend multiple times but gave up each time due to time constraints as it’s hard to find simple reference implementations.

                    I’ve been checking back over the years but it still seems hard to do this outside of Node.js.

                    • adeptima 11 hours ago

                      Same experience. Go is my default choice for backend too

                      It can easily be a full time job

                      You need to mirror all logic and encoding/decoding part

                      https://github.com/yjs/yjs/blob/main/src/utils/encoding.js

                      https://github.com/yjs/yjs/commits/main/src/utils/encoding.j...

                      I was thinking about spining off nodejs instance just for persistence and syncing with postgres

                      • jakelazaroff 6 hours ago

                        Author here — I think our own almost server is almost exactly what you’re looking for? Y-Sweet [1] is open source, written in Rust and persists documents to S3. We offer a hosted version if you want to quickly check it out, which you can use with your own S3 bucket if you want to self host eventually.

                        This is the first I’ve heard of Platejs, but we do have a tutorial on integrating a block editor using BlockNote [2]

                        [1] https://github.com/jamsocket/y-sweet

                        [2] https://docs.jamsocket.com/y-sweet/tutorials/blocknote

                      • 5Qn8mNbc2FNCiVV 11 hours ago

                        Fyi, building a collaborative editor right now and it's still hard to do outside of Node

                        • adeptima 11 hours ago

                          Still better time spend than doing leetcode.

                          It's my go-to argument against leetcode style interviews.

                          I would rather ask a candidate to spend 30 mins and do research together on collaborative editing, or visualizing distances used in pgvector or similar vector database.

                          Imagine how far the whole colabarative editing space moved forward if 1% of leetcode grinding were rerouted

                    • essentia0 10 hours ago

                      So perplexing - in the interactive demos, the latency slider acts not as a network latency but more a debounce buffer? Why? Why? I just don't get it

                      • paulgb 5 hours ago

                        We wanted to go with the simplest model of latency that would suffice to demonstrate the problems that come up when dealing with state mutated in multiple locations. The advantage of this approach is that we can do it without hiding any state from the reader — the pie chart exposes the only internal state that exists. It’s not meant to be an accurate network simulation, just to build intuition.

                      • danielEM 12 hours ago

                        > The trick is a technique called fractional indexing, in which indices are fractions rather than integers.

                        How many times you can use fractional indexing before it stops working?

                        • danielEM 12 hours ago

                          Sorry, just did that test - it is 1075, not massive, I would risk saying that may be major issue of this lib.

                          Here is the code:

                          let left = 0, right = 1

                          let rightPrevious = 2

                          let counter = 0;

                          while (right > left && right < rightPrevious) {

                              rightPrevious = right;
                          
                              right /= 2;
                          
                              counter++
                          
                          }

                          console.log(counter)

                          Did look very briefly into repo, but didn't find a place where it is handled and don't have time to dig it, but if that issue is true I may help with resolving it. LMK

                          • paulgb 12 hours ago

                            Good point. Usually fractional indexing is done with arbitrary-precision numbers to avoid exactly this issue. We landed on using JS floats to teach the technique because it makes it more intuitive to understand what’s going on, but you make a good point and I’ll make sure we add that caveat and link out to an arbitrary-precision fractional index library.

                        • oefrha 18 hours ago

                          I used Yjs in a small side project a while ago. The client side was fairly easy to learn and use. On the server side though, I wanted to deploy a single binary, but examples in languages other than Node (e.g. for the Rust port Yrs) seemed close to nonexistent, so I ended up slightly adapting https://github.com/yjs/y-websocket (Node) with persistence based on LevelDB. That's suboptimal for me. I wonder if there are good resources for implementing the server-side with persistence in, say, Rust.

                          Btw, IIRC existing resources for the client side are heavily focused on text editor integrations, so this is really helpful. I had to fumble a bit myself because I wasn't using a text editor integration.

                          • paulgb 18 hours ago

                            You might like Y-Sweet[1], an open-source Rust server that powers the banner on Learn Yjs. It uses S3 or the local filesystem for storage, and it compiles down to a musl-linked binary that weighs a few megabytes.

                            https://github.com/jamsocket/y-sweet

                            • oefrha 18 hours ago

                              Thanks, I'll look into it. It's pretty low on the list of search results for Yjs server, I somehow missed it the last time.

                          • stopachka 20 hours ago

                            The interactive demos are beautiful! Is there a library you used to build it?

                            • jakelazaroff 19 hours ago

                              Thank you! The site as a whole is built with Astro and the demos are “islands of interactivity” built with React.

                              The demos are really running Yjs under the hood — each “client” has its own document, and when the user clicks I set a timeout to simulate the latency and then manually merge the documents into each other. (There’s a third document too for the timeline in the center.)

                              Other than that, I’m using dnd kit [1] for the drag and drop functionality in the todos demo, Motion [2] for the animations and CodeMirror [3] for the text editor.

                              [1] https://dndkit.com

                              [2] https://motion.dev

                              [3] https://codemirror.net

                              • techan_liquid 4 hours ago

                                Great work Jake! I love the Astro and the “islands of interactivity”. Is it possible to see the repo, if it's public? I couldn't find it anywhere.

                                • stopachka 13 hours ago

                                  Thank you Jake! I just played with the motion website and loved it. I am going to try to use it sometime

                              • downrightmike 19 hours ago

                                The banner image game is silly but fun

                              • dangoodmanUT 17 hours ago

                                another banger from the jamsocket team

                                • sergiotapia 19 hours ago

                                  is Yjs a platform like Convex? are they competing? would love a comparison page potentially! :pray:

                                  • paulgb 19 hours ago

                                    You can think of Yjs as a protocol for data synchronization. It gives you a way to describe a JSON-like data structure (i.e. nested lists and maps), and keep them in sync across multiple devices.

                                    Yjs itself doesn't provide a platform, but it's an open protocol so there there are service providers (like ourselves[1]) that offer Yjs backends as a service (other notable providers are TipTap/Hocusocus and Liveblocks).

                                    [1] https://jamsocket.com/y-sweet

                                    • showdown 14 hours ago

                                      what's the main differences in your opinion between y-sweet and Hocuspocus?

                                      • paulgb 13 hours ago

                                        The biggest difference is that Y-Sweet is built around object storage (i.e. S3 and friends) rather than a database.

                                        This allows writes to scale horizontally without a central database being the bottleneck. It’s also a much cheaper way to store lots of documents accumulating over time on S3 than in a database. This is because compute scales with how much data you actually access, not how much data you store.

                                        I wrote about why object storage is a good fit for this here: https://digest.browsertech.com/archive/browsertech-digest-fi....

                                  • __MatrixMan__ 15 hours ago

                                    I finally got a four leaf clover and somebody ruined it after like 2m.

                                    Edit: Wait, where did everybody go? I think we broke it, or maybe I got banned. Kudos to the creator just the same. Neat stuff.

                                    • jakelazaroff 14 hours ago

                                      You definitely aren’t banned! Maybe people just tapered off for a bit — I see a bunch of cursors now.

                                      There are two more secret emojis, by the way :)