Introduction
What is DocNode
DocNode is a local-first framework. It is primarily composed of:
- DocNode Core: a highly performant type-safe document manager with atomic transactions and an undo manager. It supports Operational Transformation (OT) and in the future also a Conflict-free Replicated Data Type (CRDT) mode.
- DocNode Sync: A client-server framework for managing DocNode documents. It synchronizes documents across different tabs and clients in real time, both locally and in a central database. It supports authentication, conflict resolution, multiplexing, history version, and more.
How does it compare to Yjs?
| Feature | DocNode Core | Yjs |
|---|---|---|
| Type | ID-based OT | CRDT |
| Sync / Backend solution | DocNode Sync | Hocuspocus, Y-Sweet |
| Pricing | Free | Free |
| License | A Fair Code License | MIT |
| Types of nodes | DocNode | YMap, YArray, YText, YxmlFragment, YXmlElement, YXmlText |
| Bundle size (gzip) | 6.8 kb | 26.3 kb |
| Type-safe node schemas | ✅ | ❌ |
| Move operation | ✅ | ❌ |
| Hard deletes | ✅ | ❌ |
| Metadata-free inserts | ✅ | ❌ |
| P2P support | ❌ | ✅ |
| Schema normalization | ✅ | ❌ |
| Automatic batching | ✅ | ❌ |
| Node IDs are public | ✅ | ❌ |
Why another CRDT / OT library?
- Operational Transformation (OT): DocNode is the only actively maintained OT framework. Since it relies on a server, documents avoid soft-deletes and tombstones like CRDTs, keeping them compact. A CRDT mode is planned for scenarios requiring P2P collaboration.
- Type-safety: TypeScript is a first-class citizen. You define the shape of your nodes, and DocNode ensures correct parsing and validation.
- Performance: DocNode is incredibly fast. Updates are batched automatically, there's no double-buffering/virtual DOM, the event system is designed for fine-grained updates, and serialization is extremely small.
- Simplicity: You don't need to worry about which data type to use, since there's only one (DocNode). This makes modeling your document a near-obvious task.
- API Design: The API has gone through two years of iteration and refinement. Get ready for many aha moments.
- Composability: DocNode is designed from the ground up to support independent extensions and customizations of documents, nodes, and features without conflicts.
- Schema enforcement: Do you want your document to always start with a heading? Or never have more than five bullets in a row? DocNode lets you define your own Normalizers to enforce any structure you can imagine.
Credits & Acknowledgements
Many thanks to:
- The Lexical team, especially Dominic Gannaway, Acy Watson, Gerard Rovira, Maksim Horbachevsky, and Bob Ippolito, for the opportunity to collaborate closely and for the insightful discussions on Lexical's design. Special thanks to Bob, whose design of the new Lexical State API and the idea of Lexical Extensions strongly shaped DocNode’s approach to state management and gave it its composable nature.
- The Yjs team, Kevin Jahns and Bartosz Spytkowski, for their inspiring work and for sharing so many valuable resources through forums, blogs, and talks.
- The Loro team, Zixuan Chen and Leon Zhao, for the friendly and insightful conversations about CRDTs and for pushing the boundaries of what’s possible with them.
- The research community advancing conflict resolution strategies for collaborative editing. Special thanks to Martin Kleppmann and Joseph Gentle for their impactful contributions.
- State management libraries: Jotai, Zustand, and Pinia, which inspired the way to customize getters and setters in DocNode.
- To my beautiful wife Normi, for supporting me unconditionally in this and all my projects.
About Me
Hi, I'm German Jablonski, an Argentinian currently based in the UK and working on Payload development at Figma.
I began working on DocNode in January 2024, but my fascination with CRDTs and OT started back in 2021, when I was building my note editor Fluski.
In Fluski, not only the text editor but also other data structures, like the document tree, are CRDTs. Along the way, I faced countless challenges. That experience pushed me to dive deep into the world of rich-text editors and collaborative data structures. I set up alerts on Google Scholar, Hacker News, and Reddit, and spent years reading every paper and implementation I could find.
Had I known how much time and effort it would take to build DocNode, I probably wouldn’t have been foolish enough to start it. But looking back, I’m glad I did. The world might have missed out on something truly beautiful. What kept me going was the conviction that there had to be a simpler way to work with conflict resolution in documents. That way is now real, and I hope it helps you too.