Research Results, thus far
Current Recommendation:
- Use LiveBlocks or TipTap Free Tier
- May be the simplest solution? We may run into limitations due to the free tier
- TipTap seems a bit more comprehensive then LiveBlocks, the later just seems to be a synchornization backend + plugins
- Implement a simple spring backend for y-websockets (the reference implementation seems reasonably simple)
- Simple at first glance, may turn out to be very complicated.
- Use the automerge-java library
- Library seems to be an FFI binding to the Rust native code of automerge
- Write (part of?) backend in TypeScript and use yjs, automerge, or ot.js
- Plenty of frameworks and options, but requires two backends
- Use yjs on frontend and run a y-redis backend (backed by PostgreSQL)
- Requires PostgreSQL, Redis and JS backend
- Implement own CRDT (e.g. Logoot) based on other half-ready implementation on the internet.
- Error-Prone and will result in a suboptimal result
Side-note regarding Editors: We could consider using CodeMirror instead of Monaco. Code Mirror offers less things out-of-the-box, but is better documented, easier to embed, smaller and more flexibel. Elixir LiveBook switched from Monaco to CodeMirror. ProseMirror also seems to offer some collaboration features. Other options include e.g. Lexical.
Side-note regarding Undo: The undo feature may be very difficult to implement in a concurrent setting.
Side-note regarding Java: It seems to be exceptionally difficult to find anything working which is not JS/TS or Rust
Ideas
Operational Transformations (OTs)
Idea: Each change from each user is given a unique incrementing ID by the server. Changes are then ordered by the ID and applied. In conflict situations, changes may need to be combined/transformed to resolve conflicts for a client. Relatively simple design, but the transformation logic (e.g. combining changes and resolving conflicts) may be challanging to implement. Does not guarantee a consistent state across clients.
Libraries:
- https://ot.js.org/
- TypeScript library
- Uses Firebase for synchronization
- Has a ready-made monaco example
- https://codemirror.net/examples/collab/
- CodeMirror provides a client-side scaffolding for implementing an OT algorithm
- https://github.com/share/sharedb
- JS Database supporting collaborative editing. By an ex-Apache Wave engineer
Links explaining:
- http://operational-transformation.github.io/
- Very good visualization of an OT algorithm
- https://github.com/BaffinLee/collab-editor
- Real-time collaborative monaco editor in JS
- https://dev.to/sudoboink/the-basics-of-operational-transformation-288j
- Good intro to conflict resolution with OTs
- https://github.com/slevental/operational-transformation
- Java Code implementing a simple OT algorithm
- https://en.wikipedia.org/wiki/Operational_transformation
- Explains different OT models
- https://www3.ntu.edu.sg/scse/staff/czsun/projects/otfaq/#_Toc321146131
- Useful FAQ
- https://dl.acm.org/doi/pdf/10.1145/301308.301322
- Relevant paper I didn't bother to read, concering OTs with locking
Conflict-Free Replicated Data Types (CRDTs)
Algorithms where replicas of a document can update concurrently. Merges are guaranteed to be consistent without the complicated merge algoritms of OTs. Supports offline editing and syncing. Based on Eventual Consistency, which itself is the base of many NoSQL-Databases (e.g. Redis). Several useable algorithms, WOOT, LOGOOT and RGA are available.
Libraries:
- https://yjs.dev/
- JS/TS & Rust library
- Has a corresponding websockets library
- https://automerge.org/
- JS/TS & Rust library, competitor to yjs
- Seems to have java bindings
- https://syncedstore.org/docs/
- Based on yjs
- https://fluidframework.com/
Links explaining:
- https://medium.com/@ravernkoh/collaborative-text-editing-with-logoot-a632735f731f
- Collaborative editing with Logoot CRDTs
- https://akormous.medium.com/building-a-shared-code-editor-using-node-js-websocket-and-crdt-e84e870136a1
- Building a collaborative editor using yjs and monaco
- https://news.ycombinator.com/item?id=29507948
- On using yjs or automerge
- https://www.inkandswitch.com/peritext/
- CRDT for Rich Text, elaborates on the difficulty of preserving intent when merging markdown
- VERY useful article when implementing CRDTs from scratch
- https://josephg.com/blog/crdts-go-brrr/
- CRDTs go brrr (from the author of ShareDB)
- https://www.pierrehedkvist.com/posts/collaborative-editing-using-crdts
- Another aricle on CRDT WOOT and text collaboration
- https://discuss.yjs.dev/t/how-to-implement-data-persistence-on-the-server-side/259/2
- Diskussion on server implementation with Yjs
- https://github.com/phedkvist/crdt-woot
- Implementing a collaborative editor with CRDT WOOT
- https://inria.hal.science/inria-00071240/document
- Another CRDT WOOT paper
- https://news.ycombinator.com/item?id=34589290
- yjs vs automerge; tl;dr: yjs was faster in 2023
- https://dev.to/nyxtom/introduction-to-crdts-for-realtime-collaboration-2eb1
- Comparison of CRDT algorithms
- https://pages.lip6.fr/Marc.Shapiro/papers/rgasplit-group2016-11.pdf
- "High Responsiveness for Group Editing CRDTs"
Differential Synchronization (DS)
- https://neil.fraser.name/writing/sync/
- https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/35605.pdf
Alternatives
- https://liveblocks.io/
- Collaborative text editors with monaco or code mirror
- https://tiptap.dev/
- Collaborative markdown editor service
Other
- Most approaches can be combined with a locking of parts/elements of the document
- https://dev.to/shubham567/collaborative-coding-in-monaco-editor-4foa
- Building a dead-simple collaborative Monaco editor with Firebase
- https://christophermeiklejohn.com/crdt/2014/07/22/readings-in-crdts.html
- Collection of advanced useful links for CRDTs/OTs
Deprecated or not-production-ready libraries, as a reference
- https://github.com/opencoweb/coweb
- https://github.com/convergencelabs/monaco-collab-ext
- https://github.com/dominictarr/crdt
- https://bitbucket.org/d6y/woot/src/master/
- https://github.com/segreeeen/Yrs4J/
- https://github.com/yjs/y-redis/ <-- still interesting
- https://github.com/juliuskrah/crdt-java
- https://github.com/ravern/logoot/tree/master <-- dead simple logoot crdt implementation in Go
- https://github.com/conclave-team/conclave
- https://github.com/inkandswitch/peritext
- https://github.com/ziedbrah-source/Collaborative-Text-Editor
- https://digitalfreepen.com/2017/10/06/simple-real-time-collaborative-text-editor.html
- https://github.com/SalahAbotaleb/Online-Collaborative-Text-Editor