This is a transcript. For the full video, see A Deep Dive Into Yjs Part 2- Tag1 Team Talk #005.

  • Hello, and welcome back to another Tag1 Team Talk. Wherever you are in the world, thank you for joining us. We're gonna be talking about Yjs today. It's a wonderful day today, it's beautiful here in New York, actually, it's really not very nice, but we're joined by three wonderful guests today to talk about Yjs, a framework for collaborative editing of shared data types that you can use for collaborative editing, collaborative drawing, 3D modeling, and a whole bunch of other real-time collaborative applications. Today we're gonna talk with the founder and project lead of Yjs, who I'm gonna introduce in just a little bit here, about what actually comes into play when you wanna create an amazing collaborative app, and especially some of the more compelling features of Yjs. Especially things like awareness, offline editing, and versioning with a change history that's comprehensive. Just a quick reminder before we get started here, we've already done a couple of talks on Yjs, a couple of webinars. If you're just getting started with some of these topics you might want to go back and check out some of our history in this regard. We've got some great topics that we've talked about in the past when it comes to real-time collaborative editing, when it comes to rich text editors.

    You can find all of these at tag1.com/tagteamtalks. If you like this talk, please remember to upvote, subscribe to our channel, share it with all of your friends and colleagues, anyone who's interested in these topics. My name is Preston So, I'm based here in New York, I'm a contributing editor here at Tag1, and a moderator of the Tag Team Talks, as well as principal product manager at Gatsby. We're also joined today, out of Berlin, by Kevin Jahns. Kevin is the founder and project lead of Yjs and the real-time collaboration systems lead at Tag1.

  • Hi, everyone.

  • We're also joined today by Fabian Franz in Switzerland. He's the senior technical architect and performance lead at Tag1, leads up the development team, building an intranet with real-time collaborative editing for a top Fortune 50 company. And finally, we are joined also by my partner in crime here, Michael Meyers, based out of NYC. We're in the same time zone again, finally. Hey Mike, managing director of Tag1.

  • Hey guys, thanks for joining us today.

  • All right. I'm gonna pass the mic over to Mike just for a little bit, just, why are we talking about this again? I mean, what are we doing here, you know, why is collaboration such an important topic at Tag1?

  • We're really interested in collaboration because it is how modern workforces get things done. All day long, I'm working with the Tag1 team on collaborative applications, whether it's, you know, Agile Scrum planning, you know, we share a screen, why can't that application just be updating in real time like Google Docs? Which is another thing that we use throughout the day, all day, everyday. So we strongly believe that collaboration in real-time applications are a really important part of the future and that we're gonna see it more and more, and we're excited to be part of leading the charge, working with Kevin on Yjs and we're building out an intranet, that you mentioned, for a top Fortune 50 company and it's really exciting. It's an awesome project to work on and be part of and we'd love to do more real-time applications with organizations so hit us up at tagteamtalks@tag1consulting.com if you guys wanna talk about more topics or how we can help you add it to your application.

  • And it's definitely true that Tag1 has been at the vanguard of real-time collaboration. Obviously, early adopters of Yjs, an amazing framework. But, for those of us who have just joined today, all of the listeners and all the viewers who are a little bit behind, maybe they're still catching up on some of the previous Tag Team Talks we've given about Yjs, let's go ahead and cover a little bit about what we talked about in part one. Now, Fabian, I remember you mentioning just before we got on this webinar that you've got a really great illustration of kind of the difference between what we call CRDT, Commutative Data Replicated Types, and OT. You wanna go ahead and jump into that explanation a little bit?

  • Yeah, definitely. Hello, and welcome, I'm really glad to be here again. So collaborative editing is basically about, at the very simplest level, we're inserting characters. And last time, I was talking about universes, and objects, et cetera, but I found a much better way to describe that and it has to do with New York. That's so cool that you are both here again. You get to New York, just like Germany, you talk about blocks. You talk about blocks all the way, all the way. This is just five blocks away, so you count five blocks and you go there. And this is kinda how OT works, you say, this is five blocks away, but if you've gone two blocks it's just three blocks away. But the other thing is, this is King Street 55, and regardless of where you are in the town, King Street 55 is, hopefully, always at the same place. And that's kinda the one minute explanation of how you can think about those two things. The one thing is addressed positions which you need to change, and the other part is addresses, and CRDT has addresses while OT has positions. And that's it.

  • That was just an amazing metaphor. I mean, I've never heard about describing relative location versus kind of absolute location. This is a really great illustration of that difference. Now let's just hop over briefly to Yjs. Now, Kevin, I understand that, you know, Yjs was built to enable developers to really leverage these benefits of distributed systems, create peer-to-peer, these offline-ready collaborative apps. I mean, how exactly does the Yjs project work, and how does it model data internally? Just very briefly, as a summary for our viewers today.

  • Right, so in our last talk we talked about how Yjs represents characters in its data model and we talked a bit about how it resolves conflicts when two users insert something concurrently at the same time. We gave some examples on how structs are represented in the Yjs data model, maybe we can talk more about that later because there are some more things that we can cover. So yeah, we talked about that Yjs itself, the framework, it only handles concurrency, conflict resolution, and data types. All the other things, for example, communication to other servers, or storing data updates in a database, or the data bindings to other editors so you can actually collaborate in text editors, or, for example, how you build drawing apps, these are all separate modules that you can include and they are maintained in the Yjs organization. And I, again, invite you to build more modules for that if you have a really nice, if you're the maintainer, or you know a framework really well. For example, a diagram application, write integrations for Yjs and share that knowledge.

  • That's amazing, I think, you know, one of the things I would love to see is a lot more of these amazing tools that we see used in the wild leverage Yjs and really get to the point where not only can a lot of our content editors and folks working with text use this, but also people who are working with drawings and drafting and doing all of these more kind of real, or less abstract things with real time. That's really great. One of the things we talked about last time, just very briefly, was kind of the three key pieces of a collaborative app, and I want to go through each of these in turn. We talked about awareness and, you know, I'm gonna defer to you, Kevin, on defining that better because I think you've got a really great definition there, offline editing, and also versions and providing a change history. All three of those are really important aspects of these collaborative applications. Let's talk about the first one, awareness. What exactly does awareness mean in this context and what are some examples of what you mean when you say awareness, Kevin?

  • Right, that's an awesome question, and I think there are a lot of people who could go on and on about awareness. You know that awareness is actually a research topic and there are dedicated journals that only talk about awareness features? Awareness is a really broad topic. Just to give an example what awareness is, we are currently in a meeting, we have a video-conferencing solution, I can see what you are doing, I can see how you feel, if you're smiling, if you're currently talking or doing something else. This is all awareness information and there are lots of different levels of awareness, and with technology we created more methods to express awareness of what is currently happening and what is going on. An example of a thing that has a very high level of awareness, it is a meeting where you are in the same room and you're talking to each other and you're discussing a topic, you're all focusing on the same task and this is a lot of awareness and therefore a lot of collaboration happening in the same room. And I think a meeting room is probably the best place to collaborate with each other, to talk and to find solutions. But it also distracts you from really doing something, right? If you're in a meeting room you can't really work on your computer because you need to participate in the discussion, and that's also why developers mostly hate meetings because we can't really do something, so that's my take on that. I like to have a bit less of awareness, for example, video-conferencing solutions, awesome, I can just hop off, I can turn off my video camera and do something else. And another example of, like, no awareness or very, very little awareness is when we work on, for example with Git, on a project, we are really focusing on a single task. There's very, very little awareness because we don't really know what other people are doing. Git is a collaborative solution and it's inherently collaborative, right? It's basically like Yjs but with manual merging, you need to do everything manually, you need to commit pushes, pull branches, and all this stuff, and the only way to know what other people are doing, just with Git, it is by pulling the branches of other developers and checking out what they did in the past. So they have very little awareness. And the last example that I wanted to give is chat applications, for example, WhatsApp, we all love WhatsApp, and I think the main reason I love WhatsApp is because I always know what people are currently doing and there's some nice features, for example, when I send a message, I know that they received my message. This is also a kind of awareness because I know they read my message or they received my message, I know if they're currently online or if they're currently offline, I know when they last checked their phone for messages and if they just ignored my message, just didn't read it, and I also know if they read my message and didn't reply to it. We all know this feeling, right? You see that somebody is online, you send a message to him, and you want to query some knowledge, or if you want an answer, you see he's online and then you see, oh, he read the message, it's awesome, just a few more seconds and then I'm gonna get a reply, and sometimes they don't reply, sometimes they do, but it really fosters interaction because that other person also knows that the other person knows that he read this message. So awareness is always a tool to foster collaboration, to improve collaboration, and we need to find the right amount of awareness to really get the task done. In collaborative editing, we mostly always have a user list where we know who's currently online, who's currently editing, and you also know if they're currently offline, or, in Google Docs, you also see if they're actively working on the document or if they are just on another tab and they still have the tab of the document open. And of course, you see the user cursors jumping around in there. We can, just with all this information with the cursors, we can make our mind of what other people are doing and, well, and we know if they are working on the same paragraph as I do. So that really helps to collaborate and work at the same time.

  • Yeah. I'd like to extend that a little bit. I really love the definition of awareness here, but just to give people a little bit more visual about it, think about your text editor, and now think about a ghost, and suddenly things change within your text editor magically, crazy stuff happening, and you're like, oh, what's happening? Or you're typing something, the ghost is typing something, you're typing something, you're conflicting all the time, and awareness helps to avoid all of that because, as Kevin said, awareness in a text editor gives the information who is editing with you, are there 200 people, are there 12 people, or just one other people, or are you even alone and can just focus and get your text done? And it also helps you understand kind of, like, what are they doing? And that's one very, very important point, as we've seen before, conflict resolution is very, very hard because you never really know, there are several ways to resolve conflict and they will always be resolved in the same way, but still, if it's two people who are typing at the same point, it could still lead to a little bit of garbage in all of that. And awareness helps us as humans to avoid conflicts naturally because now, oh, you're working on that paragraph, I'll work on the next one, or you're working on this document, okay, I'll drink some coffee until you're finished and then I'll do some more comments on what you've done until you're finished because I can see you're finished, you're right now inactive and drinking coffee yourself. So that's kind of what awareness brings us there from a business value or human value, in that we can naturally avoid conflicts, so we can enhance the technology with what we humans can do.

  • Right. That again shows me how important awareness is. There are so many ways to use awareness information, also for conflict resolution. I didn't actually thought about that, but it's so right. We use awareness for all kinds of information to make up our minds to focus on different tasks. If somebody is working on a paragraph, we won't work on that paragraph actively because we know that another person is actively doing something there, so we probably won't really interact with him that much, or only if we have to, if we really have a good idea. So this awareness, it's really a feature that we can integrate in any collaborative app, and we see it in so many collaborative apps and it would be--

  • [Fabian] Oh, sorry.

  • It's fine. Yeah, I just wanted to conclude that it really enhances collaborative apps, and I think that a collaborative app without awareness would be so boring and it wouldn't really help us to achieve a task.

  • Yeah, also what I found really important here about this awareness is kinda, if you're working, like, in isolation and completely, you're really not getting to the point of, that it's fun. Collaborative applications without awareness, they would not be fun, they would not be nice, and this is really giving us so much value and being able to get stuff done.

  • Yeah, very true. I think that awareness, the main dimensions that we talked about, and obviously there are many metaphors we can use for this, but I think we see that it's an incredibly important tool to allow people to see and understand the context, and that's ultimately what is key here. I see, Fabian, you want add something there.

  • Yeah, I finally remembered what I wanted to say. No, what's really important is about, there's a difference where we have to decide, now more technical, between awareness and things. There's things that are part of the document, that are part of the final product that is finished, which is, in our case of collaborative text document, a text document. However, awareness is something that happens all the time and changes all the time, and I would even go so far that, for example, comments inside Google Docs are part of awareness and not part of my document because in the end, if I save the document, the comments are gone. They're just displayed, I have my PDF, I have my end result, where the comments are really a way of communicating within the document itself, and again, to have awareness. For example, I see a typo, I fix it for you, but I don't fix it directly because maybe you want to misspell it, and you can see, hey, he made a change, I'm gonna accept this change because I really want to. So I bring it to your awareness that there's a typo, or I bring it to your awareness that I think that this sentence really does not belong, or that I really think this sentence is great and we should be doing more of that. And again, these are ways of collaborating within the environment but without touching the actual end product, and I think that's a very important distinction to make.

  • Absolutely. And now, I know that we, you know, one of the biggest places that we see awareness and the biggest example of this, I think, in terms of Yjs is shared cursors. How do those work exactly in this context? Could you explain a little bit more, kind of, how is it that we're able to get all of these cursors to play well together within the Yjs landscape?

  • Right, so in Yjs there's an awareness feature and I named it that way because this feature allows you to implement, well, awareness features. So this protocol, it's actually a new protocol that is built on top of Yjs. If you would implement awareness features with shared types, with a CRDT for example, if you would insert a cursor location as a struct element into the structure, this would really blow up your document size, right, because you jumped around so much with your cursor, so you shouldn't make that part of the CRDT model. In Yjs the idea is we just exchange, if we are talking about the cursor location, we just exchange the ID of the struct where we are currently pointing to. For example, if we are working on text A-B-C, we know that each character in Yjs is uniquely addressed, so when we create a cursor we compute to which location we are currently pointing, for example, if we are to the left of the character A, we broadcast the message my cursor location is currently just before character A, and this is how other users know where to insert that cursor, and it plays nicely when other people are currently also working on the document because just changing, inserting content before that and after that, doesn't really change the location of the cursor because it will always point to that character A where we have our cursor location at the moment. So it plays nicely with concurrency. In other solutions, for example in OT, everything is position-based. You would say my cursor currently points at position zero, and when somebody else is actively inserting something before zero, your cursor location would not point to character A anymore, but to something else. So in Yjs this is really nicely solved. And the awareness protocol itself, it solves more than just cursor locations. It is currently part of the y-protocols repository, and y-protocols implements awareness as just messages that are broadcasted and have a unique ID. Just to give an example, if I broadcast my first message, okay, I'm online, this would get an ID one, so this is very different from the CRDT solution because this is not really concurrency, it is just messages that are broadcasted by your local environment. So your first message would be, hi, I'm online, and your second message would be, I changed my cursor location to that character, and you also broadcast that message with an increasing ID or increasing clock so other people know what to update. The protocol that is implemented by y-protocols, it is also safe for concurrency and it is also safe for, you can apply these messages in any order, and this is what we talked about in the last talk, and it means messages are communatitive, ah, sorry, and it basically means you can apply these messages in any order which is really important if you want to build a P2P network. Yeah, so this is how awareness is currently implemented. It's its own protocol, it's not really part of Yjs, but it's part of the ecosystem.

  • That's amazing. You know, I think that the amount of thought that you've put into this really shows that anyone who relies on these features is gonna be very, very, you know, very well-equipped with what they need, especially in terms of what we've discussed around awareness. We wanna move on a little bit now, just to jump into kind of the next topic of interest, I think, for our audience which is how do we exactly support offline editing? And I know that, Kevin, you've done a lot of work around how these things work in terms of Yjs structs, and I'm kinda curious, you know, you mentioned just now these notions of commutativity, how exactly does that work from the context of offline editing?

  • Right, so, I didn't really think about this offline editing approach a lot there when I first started with shared editing. I thought when you work offline you just store your, I'm sorry, I wanted to say something different. I wanted to talk to you about how these messages are stored, and later we will talk about something else. How does that work? It's actually really simple, let me share my screen, please. I'm still here, Fabian is here. Can you see my screen?

  • [Preston] We're seeing a white screen right now.

  • [Kevin] Oh, that's a bother.

  • [Preston] We can edit all this out.

  • Yeah, we need to. That's good. Ah, picture.

  • [Preston] There we go!

  • All right. Go here, all right, you can see my screen. All right, I want to talk to you about how document updates are stored offline. The idea is pretty simple, we currently just send messages to other peers and this is how we sync documents. We can also just store all the document updates in a single database. The idea is just as simple as that. So, in this talk I also wanted to talk a bit about how delete operations are encoded in Yjs, and then you can see how the Yjs model is encoded and stored offline. So we talked, I still have my whiteboards open, we talked about conflict resolutions in one of our last talks, we gave some examples here, and, well, there is nothing here, all right. We talked about how a struct is represented, so it always has a content, which is, for example, a character, and it also has a unique ID which is a clock vector, for example, in this case it would be client one and clock zero. So this is basically the main structure of a struct, and we have a different kind of notions if we want represent delete operations because they are not encoded as structs, they are encoded as a different set. Here an example of how we encode that is we just say, when I create a delete operation, I delete from client one n operations, so this is the amount of operations that we want to delete, and if we have two operations that we want to delete we would say, I'm sorry, we may need to, I didn't really prepare this. We may need to snip this. Do you think this is helpful, what I'm telling you about?

  • [Fabian] Yeah, definitely.

  • [Preston] Yeah, absolutely.

  • [Kevin] You think so?

  • It's a little bit recap but, yeah, that's fine.

  • Okay, all right. Can I start again? Just with this, please.

  • [Preston] Yep.

  • All right. Okay, sorry for our break, we had some technical difficulties. I wanted to talk to you about, again, how we encode structs and how we encode delete operations. So in our last talk we talked about that structs are encoded as they have content, for example, character A, B, C. So this particular struct is consisted of three operations. And each struct, of course, also has an ID. In this case it would be user one, clock zero, and if you watch our last talk again you will see that this is one of the unique features of Yjs, that you can encode several characters as a single struct. So the first character, A, would be represented as user one, clock zero, the next character, B, would be represented as user one, clock one, and so on, C would have the clock three, and this is one of the optimizations of Yjs. Now, what happens when we want to delete an operation? We would say delete an operation from user one, so this is user, and we want to delete the character A and B, so we say delete starting with clock zero, so this is the clock, and delete two operations. And again, this merging of operations, this merging of structs, really comes in handy because now we can also represent delete operations much more efficiently. Okay, we say delete two structs, so after the delete is applied this struct would be split into two structs where the first two characters are marked as deleted. So structs don't really have any information about if they're deleted or not. The delete information is powered off the delete store in Yjs. So there when we encode the Yjs model what we are actually doing is we encode all the structs very efficiently in a binary blob, and we encode all the delete operations, also very efficiently, because we can merge these delete operations. Here's an example, if we create our next delete operation which would be one, well, we already deleted zero, which would be one, two, one, so delete from user one, with clock two, one operation, then all the characters, A, B, C would be deleted and we could merge these two into, oh, I can't, okay, we would merge these two into one, zero, three. So again, this merging comes in handy, and it really pays off if we have a lot of information to encode. So this is what we would encode and then store in a database. We can encode the whole document as a single block consisting of all the structs and all the delete operations, and we can also send all this information over the wire. All right, this was a really long explanation how offline editing works, we just encode the data model and I just did a recap on how we encode delete operations because it really bothered me that we didn't cover that in our last talk.

  • No, absolutely, this was very useful, and I feel like I really understand how deletions work now. It's a very, very clever and graceful approach. I really appreciate the full explanation. Now, you know, next thing is, we've talked about awareness, we've talked about shared cursors, we've also talked about offline editing and how that works within Yjs, showcasing how those delete operations get transmitted to the database. The next thing I wanna ask you about though, Kevin, is more about kind of, you know, about the content governance aspect. How does Yjs handle versioning and change history, and what are some good examples of how that works in the wild?

  • Right, and here the delete operations really come in handy because this is what I need to explain so we can really go into how that works. So a version would be nothing more than the state vector, and I think we also covered that in our last talk, a state vector basically being... All right, again, picture, okay. Now it works, okay, I got more experience in using it now. All right, let's create another tab here. We talked in our last talk how structs, how the document model, can be represented as some kind of state vector. So when we have two structs from user one, for example, they have ID, user zero and ID one, we know that we have struct zero, zero, and we have struct zero, one, so let's just say we have two structs. The state vector would be just a map, an actual JavaScript map, actually, just let's represent that as a hash set. So user zero has exactly one operation and if we have another struct from user one, and for example, we might have six operations from that user, so this would be the state vector, and the state vector represents--

  • Sorry for interrupting. So this would be kind of like the last clock I've seen from a user?

  • Exactly, yeah. Thanks for clarifying that. The clock basically represents the amount of operations that you received, and if we received one operation the next expected clock from user zero would be clock one, and this is how we know how many structs we have and which structs we expect from the other users, and we covered that in the last talk, in order to sync messages, in order to find out what is still missing, and what we didn't cover is how deletes are exchanged and how we represent deletes in the state vector. So this state vector, it encodes the amount of structs we have at a particular point in time. The next thing that we need to cover is what kind of, oh, that's a cute dog, the next thing that we need to cover is how many, which characters and which structs are deleted, and this is where the delete set comes in handy. So, the versioning vector basically consists of the state vector and the amount of deletes, and yeah, this is how we find out if we want to restore a specific version from a, man, I feel like, I should have prepared that, I'm so sorry.

  • Let me quickly ask some clarifying questions. So usually if I've used the document what I have is revisions. I have one increasing counter, I have a version one, I have a version two, I have a version 1000, I have a version 2000, et cetera. But now I'm collaborative, I don't even have a central server, so this just doesn't work anymore because, well, if I say, hey, I have version 1000, and you say you have version 1000, we are conflicting. So either we have a central server which is giving us its versions or we need some other way. But we all have increasing clocks and we all have unique client IDs. So in the same way that I had a version 1000, I can now connect and say, hey, I have version 600, and you have version 400, and together we would be kinda at version 1000 in the same way, kinda, because in that, for just us two, we would be having this 1000 revisions together made, collaboratively, obviously, but that way we can basically show a distributed revision history. So I have my revisions, you have your revisions, but together we have the revisions for the whole document, so every one of our states is still unique. If I increase mine to 601, we have a new document now, and that's at least how I understand what you've explained so far.

  • That's actually exact. So I should've covered how, what the actual problem is when we want to have a state vector, when we want to express how the document looks like at a certain point in time, what we want to do is to really make a snapshot of, okay, this is the state at this time and how do we represent this state in Yjs, and this would be by using a state vector on the structs and by using the delete set that represents which structs are deleted at a certain point in time because a problem that you also talked about, Fabian, is how do we represent states if we have a distributed system? It is a really hard problem because, of course, we can make a snapshot of the content at a certain point, but something that we also want to do, and we will talk maybe about that in a few minutes, is how do we find out who made the changes. For example, if we have this character here, who made this change? We know by the user ID. But we also want to know who deleted that character, and this would be by having delete sets.

  • Oh, so basically I'm only inserting into this document and if I want to delete something I insert after that character, kinda, this character is now deleted.

  • Yeah, yeah, because deletes don't really show you who did this delete operation, it only shows you which operation was deleted from which user, but you don't know who did it, right? So there need to be some more methods to track this information.

  • Definitely. If I were just deleting then, yeah, anyone that ever tried in Git to figure out where a line of code originally has come from have probably gone through a lot of patches where the line was added, it was deleted somewhere else, then it was added somewhere else, it was deleted somewhere, and you go back and back and you can never really figure out who, or in the end you find out it was recent edited in 2006, but, yeah. That's a nice way to circumvent that problem.

  • Yeah, it's true, and we know this problem also from GitHub, for example, where we express changes as diffs on a text document, and it's really handy, we can track those changes because we have a linear history of changes, but in Yjs we don't really have a linear history, we can merge in all kinds of ways. We don't have a central hub that organizes the changes in a certain way so we need to come up with more solutions to do that, and the approach that I chose for Yjs to track who did what, and to track also what a state at a specific point in time means is by using state vectors and delete sets, and they are also helpful to represent who deleted something because in order, we have this set of delete operations that we defined here, and what we can now say is we assign all the set of deletes to a specific user. So let's say all these deletes here that are defined here, that are also merged internally, they belong to a certain user. Let's say these deletes are from user three, but they delete operations from user one, so this is how we know who deleted something and we know who inserted something because this was inserted by user one and this doesn't change. So now we just need to track who user one is and in any point in time, with any version, we can now track who did what, who did the deletes, who did the insertions, and with that information we can compute tracked changes, or, like, versioning, or, like, we can find out who did what. This is basically the feature that you know from Google Docs or from git-blame. In git-blame you can say who modified that line the last time I was here. In Google Docs you have some kind of versioning system where you can see the difference between the versions. You can do all kinds of stuff with this information. It's everything that you need.

  • So just a really quick question to you, offline editing here because I think it's really related in that if I started with, like, again, our example, I'm at revision 600, you're at revision 400, now I'm going on a flight and I continue working on it for an hour and then, being me, I've made 400 corrections, changes operations, so I'm now at revision 1000. So now I'm syncing back with you and then you still kinda have our old state kinda because, you know, the last time you've seen me I'd been at 400, and then you now will kinda, what my state kinda had been. Would that be kinda correct in how I can start to sync offline my changes on the flight now with yours?

  • Yeah, that's right. So one idea to do that is, as you said, to store the state, to store the version that you have before syncing to the server and then compare that to the state that you have after syncing to the server, and that's how you know what happened in between. So if you're the person who commits changes that you did after being on the flight, something you could do is you could check your changes before committing them to the server. If you are the person that receives those changes you want to know what happened while Fabian was on the plane and did all those changes. Did they conflict with the changes that I did while I was offline? That's what you need to find out and I think--

  • I think that's a very important point here again, the human versus the technical element. Technical excellence, and that means I have rewritten all the document, moved all your changes, and done everything differently, now I sync back and for conflict resolution, for some reason, I win, and now all the other changes you've done within an hour doing that are also, they're just gone, you fixed all my typos, and it's just gone because I've rewritten everything anyway. So, and the human element here is that while auto-merging, this kinda approach of we automatically merge, is nice, it does not factor in the human factor in that really what we what we wanna know is, hey, I've made all those changes, are those even compatible in that? What do I need to do? And that also coming in to the tracked changes, what have you done, what have I done? And the other part is kinda you see, hey, Fabian rewrote all the document. That's really not what I want, I really want to reject that. I really don't want to do that. I want to undo what he has done and just keep certain parts and rework them into the document. I think that's a very, very important part also for future work on things. The automatic merging, it's done automatically, that's what makes Yjs great and CRDTs great, but the conflict resolution, it still needs this human element because we still need to now, at least for now, maybe robots can do it in the future, but for now we need to know what makes sense in merging all of that. I think that's a very important part of that, that tracked changes and offline editing are way more intertwined than we would have thought before.

  • That's a really good conclusion. Actually, when I started with Yjs, I didn't really think about this track changes feature. It was something that I just recently added, like, not that recently, just a year ago. I started with the track changes approaches and basically it boiled down to what we have now with expressing the state as versionings and how you can track who deleted something and who inserted something. I think there haven't been any approaches like that before, and I read a lot of papers about this and the main idea in other approaches is to just restore to a older state. But something that you miss is you are in a peer-to-peer environment, like, you need to make assumptions that other users are working offline and in a non-linear manner without a server. So you need to be able to express any kind of state and history and, yeah, this is basically what it comes down to and I think you can do everything with that, and there are a lot of things that we need to explore like, Google Docs did an awesome approach to do that, I love Google Docs for that and a lot of people have followed, for example, Dropbox Paper. I also love their track changes feature where you can see what happened in the past, that you have versions that you can name, it's really awesome, but there's a lot more to do especially for other applications, for example, how could that work with drawing apps? I would be really interested in that or even with other apps because in the future I think we will be able to have way more offline-capable applications and we need to be able to show the user what happened while they were offline or while they were not participating, so you need to be able to create custom versions, or custom tracked changes for a specific user. For example, if you have been offline for a week and you have not been participating in the collaboration, you missed a lot of information. Meanwhile, Michael, for example, might have been really, really active in this collaboration part and he has been online every day and he didn't miss a lot of information, so we can really show to Michael these smalls things that happened while he was away and show you all the big history that happened while you were away.

  • And you'll never know what happened next. But perhaps you will?

  • That's a great cliffhanger. Both for anyone who is jumping in after a long time out of a document, but also for us here. You know, I did want to get to kind of the types that you have in Yjs and sort of compare and contrast Yjs to other frameworks, but I think we're gonna have to save that for next time. There's so much good material here and information. So one of the things I do want to say as well for our viewers and listeners is that one of our next Tag Team Talks, we're actually gonna be talking more about how actually to use Yjs and leverage the framework to build some of these collaborative applications that have some of these features that we've been talking about for the last few minutes here, about offline editing, awareness, and, of course, as Fabian mentioned, the how inextricably tied together change tracking and versioning are with offline editing. We'll show a lot of demo applications coming up soon also with Yjs. We want to talk about collaborative drawing, 3D drawing, text editing, and talk more about how Tag1 is leading the way in terms of building these collaborative applications. With that being said, I do want to thank our team today here, Fabian Franz in Switzerland, Kevin Jahns in Berlin, Michael and myself here in New York. All the links that we're mentioning today are in the description, just scroll down if you're on YouTube and check out all the links that we've got, or if you're on the blog post there's all of them listed there as well. By the way, we post all these talks at tag1.com/tagteamtalks, and please don't forget to check out previous webinar that we just did recently about Yjs, a deeper dive, as well as collaborative editing to get the ground for all of this underway in your mind. Thank you so much for joining us today. Please remember to share, upvote, subscribe, and share this with everyone you know, including your mail person, and I want to thank everyone all around the world today who's joining us. Thank you, and until next time.