
Lessons learned from creating a real-time collaborative rich-text editor - Reinmar
https://ckeditor.com/blog/Lessons-learned-from-creating-a-rich-text-editor-with-real-time-collaboration/
======
codetrotter
> We were quite seriously scared of repeating the infamous history of Netscape
> which was a well-known example of failing to successfully release a newer
> version of a popular software after deciding to rewrite it from scratch.
> Fortunately it did not happen in our case.

Big kudos for pulling it off!

> Two main candidates are Operational Transformation (OT) and Conflict-Free
> Replicated Data Type (CRDT). We chose OT and perhaps one day we will write
> down our thoughts on the ongoing OT vs. CRDT battle.

Please do, I would love to hear your thoughts on OT vs CRDT!

~~~
sroussey
Ditto. Would love to hear more about the OT vs CRDT decision!

~~~
codebeaker
You both may enjoy [http://archagon.net/blog/2018/03/24/data-laced-with-
history/](http://archagon.net/blog/2018/03/24/data-laced-with-history/) if you
haven't seen it already, it's an absolute gem, and touches on exactly this.

~~~
codetrotter
Thank you for the suggestion, that was a very enjoyable read indeed :)

Thanks to the author as well, for distilling so much information into the very
readable document that this was.

One thing I am wondering about is in the conclusion of the document, the
author says:

> You’d be hard-pressed to use CRDTs in data-heavy scenarios such as screen
> sharing or video editing.

With regards to video editing, could it not be rather doable after all?

Consider a non-linear video editing system (NLVE) [1] like Adobe Premiere Pro
[2].

While the size of the video data source material you are editing might range
into probably several hundreds of gigabytes for a 4K feature length film, the
project file itself remains very small, because the video data is kept
separate from the timeline data.

Wikipedia explains:

> Non-destructive editing is a form of audio, video, or image editing in which
> the original content is not modified in the course of editing; instead the
> edits are specified and modified by specialized software. A pointer-based
> playlist, effectively an edit decision list (EDL), for video or a directed
> acyclic graph for still images is used to keep track of edits.

Are these not in fact the sorts of data structures that would lend themselves
the most naturally to being implemented as CRDTs? :D

As for the video source material that is used in the project, those files can
be distributed by users outside of the editor software using for example
BitTorrent, or they could be automatically distributed by the editor software
via for example public IPFS or a private Dropbox folder, or if the users that
are working together are on a shared network then the source files could be
located on a shared NAS.

[1]: [https://en.wikipedia.org/wiki/Non-
linear_editing_system](https://en.wikipedia.org/wiki/Non-
linear_editing_system)

[2]:
[https://en.wikipedia.org/wiki/Adobe_Premiere_Pro](https://en.wikipedia.org/wiki/Adobe_Premiere_Pro)

------
fabricexpert
> The number of tests: 12500

> Code coverage: 100%

> Development team: 25+

> Estimated number of man-days: 42 man-years (until September 2018), including
> time spent on writing tools to support the project like mgit and Umberto
> (the documentation generator used to build the project documentation)

Software is expensive

~~~
_mrmnmly
show this stats next time the junior dev will say that she/he will develop own
WYSIWYG editor in like 1-2 weeks for the project needs ;)

~~~
fabricexpert
`import editor from CKEditor`

or something like that ;-)

------
pg_bot
For anyone interested in this issue I would suggest taking a look a Neil
Fraser's Differential Synchronization.[0] It took me 2 weeks as a solo
developer to add real time collaborative editing to our product using that
method.

[0]:
[https://neil.fraser.name/writing/sync/](https://neil.fraser.name/writing/sync/)

~~~
cpcallen
Differential synchronisation works very well indeed for plain text, but as
Neil himself has pointed out, it doesn't necessarily work well for tree-
structured data (like XML or JSON) because there's no guarantee that the
combination of separate syntactic-validity-preserving edits will necessarily
be syntactically valid.

~~~
pg_bot
The solution to this problem is to add a translation layer from the tree
structure to plain text. If you can do that you can work on any arbitrary data
structure easily. I'll leave it up to the reader how to figure out how to do
it ;)

~~~
Reinmar
We've been there (although, in case of OT). When implementing CKEditor 5, we
started with a linear model and just a couple type of operations (the usual
set). At that time, we weren't able to transform that linear model to a tree
model because conflict resolution based on that simple set of operations was
too dumb. As I mentioned in the other comment about CRDT vs OT, we'd still
consider having a linear + tree model duet, but so far it's purely theoretical
discussion whether it has a chance to work.

------
wpietri
Nice article. This is a great example of how Domain-Driven Design pays off. By
really paying attention to how users think of the problem and expressing that
in their design, they ended up with a richer domain model which in turn let
them get better code _and_ a better user experience.

~~~
Reinmar
Thanks! A good UX was indeed one of our main goals and we weren't sure whether
we're not overdoing this (again, the Netscape history ;|). But we kept in mind
that simpler solutions already exist and it doesn't make sense to just copy
them. That'd make the job easier, but we'd end up with the same issues that we
identified in the existing platforms (annoying conflict resolution, stability
issues, platform limitations to linear content – no tables, no nested blocks).
So we risked taking the long path. The UX served as a compass and allowed
making some reasonable shortcuts in some non-critical places. If we'd try to
solve all possible issues that we've hit, we'd still be in the starting point
:D

------
pier25
It says on the pricing page that CKEditor 5 has "GPL 2+ copyleft Open Source"
license. Can someone ELI5 that?

[https://ckeditor.com/ckeditor-5/pricing/](https://ckeditor.com/ckeditor-5/pricing/)

~~~
coder543
I guess you have to make your whole frontend open source if you use their
editor under that license? I'm not sure how GPL interacts with scripting
languages. Do you have to run GPL scripts on a GPL'd interpreter for it to be
permissible?

Regardless, the pricing for their commercial offering seems really intense.
$29/mo for 25 MAU? I feel like they're missing a few zeroes there. Maybe they
meant 2,500 MAU? 25,000 MAU? The demo I played with makes it clear that the
editor component is rather nice, but I would rather look at alternatives at
that price. I would imagine the collaborative nature is what influences the
price, but somehow Google Docs and MS Office do fine with collaboration as a
core product feature without charging >$1/MAU just for that feature.

~~~
lucideer
> _the pricing for their commercial offering seems really intense. $29 /mo for
> 25 MAU?_

The page doesn't seem to imply that the price for 25+ users would scale
linearly; for that they have a "Contact Us" call to action for negotiating
pricing.

25 MAU seems reasonable to me for the following use-case: Company A sells a
custom CMS to Company B, with a CKEditor-powered admin area to be used by <25
of Company B's content writing staff.

~~~
stalq
>The page doesn't seem to imply that the price for 25+ users would scale
linearly; for that they have a "Contact Us" call to action for negotiating
pricing.

I confirm that! It is just a specific offering for a small project where 25
people team use our editor. It's a fair price (covers granting the commercial
license, the right to use / change / hide our code, enterprise support,
maintenance, warranties, indemnifications, etc). For bigger projects we always
try to implement a licensing scenario that works well for a given customer.
Contact us and we will do our best to craft you an optimal plan.

~~~
kondro
It might be worthwhile putting some bracketing or aspirational pricing up
there with it too then as you’re potentially scaring away potential commercial
clients who look at that price and can’t see how they could justify its
inclusion at a prices they would have to guess at using that as a base.

------
marijn
Nice! I too, would love to read more on the OT/CRDT trade-off.

Companion reading (the approach taken in ProseMirror, which was implemented in
significantly less person-years):
[http://marijnhaverbeke.nl/blog/collaborative-
editing.html](http://marijnhaverbeke.nl/blog/collaborative-editing.html)

------
fovc
Do you ever garbage collect the graveyard? I wrote a tree based OT (slightly
different domain) and never found a great solution for that.

~~~
scofalik
Interesting question! Actually, at the moment we don’t :).

We did some testing to see how big this issue is and it turned out that it's
not dramatic. The main difficulty with graveyard purging is that you need to
keep the undo in mind. Elements in the graveyard are used for undo, so garbage
collecting will have to be strictly connected with limiting undo steps.

Add to that collaborative changes and it becomes a tougher problem. Therefore,
we'd probably start from what seems to be the safest option – trimming the
history stack and implementing a garbage collector that goes through all the
possible reference points.

~~~
fovc
Yup. Ran into the same thing.

Another Q for you if you're still around: did you have to make any changes to
your algorithm for when it's running through the undo queue, or is it
basically the same thing but in reverse? I found some operations could better
preserve intention with some adjustments to the undo transform

~~~
scofalik
Oh, don't get me started on modifications we needed to do to make undo look
reasonable ... :) At first, we thought that undo is the same thing as
collaboration but... nope.

The crucial difference is that with undo you have a context (old document
state). With collaboration, you don't. So if both users put a character at the
same position, in collaboration the order of output doesn't matter (and can't
be solved really). In undo it does, because a user remembers what was the
order of the letters before they made a change.

~~~
fovc
We should compare notes some time :) Sounds like we had to solve a lot of the
same issues and the dearth of info on this topic is surprising!

------
zawerf
Is there a sharedb compatible OT type definition? Like how
[https://github.com/ottypes/rich-text](https://github.com/ottypes/rich-text)
exists for Quill?
[https://quilljs.com/docs/delta/](https://quilljs.com/docs/delta/)

Also is it possible for third party plugins to add new operations (defining
their own conflict resolution against the existing types)?

~~~
scofalik
Our first idea was to have four basic operations (insert, move, attribute,
remove) and then have “deltas” (wrap delta, unwrap delta, merge delta, split
delta) which were built using those operations and for which we described
additional transformation cases. In this approach operation transformations
were set in stone, but you could add your own deltas and provide your own
transformations for them.

In the end, we concluded that users will see defining deltas and
transformations as too complicated and won’t use it. Later, we also decided to
drop deltas idea at all and we rewrote deltas into operations.

As an alternative solution, we provide the post-fixing mechanism. Your plugin
can listen to all the changes done on the model and apply fixes if something
has gone wrong. We used it for the famous "insert table row / insert table
column" problem, to add the missing cell. This alternative is not as clean as
explicitly providing a transformation algorithm but it is much easier to
implement.

The problem with defining your own operations is that you need to write
transformations against all the other operations which is a huuuuge work. It
took as a few years and we still see some room for improvement.

------
tomcam
Amazingly good illustrations. Whoever did that should illustrate all the
books.

~~~
tabtab
While I generally agree they are nice, one nit is that some of the fonts are
unnecessarily small and/or faded. It looks to me they could be made more
visible without sacrificing the visual utility of the diagrams. Roughly 1/3 of
the population would have age-related vision difficulties with those kinds of
fonts. Every graphic designer should take courses in accessibility.

------
stevetodd
Been searching for a bit and it appears that the real-time collaboration part
isn't open source and requires you to use their cloud service to make it work.
The pricing for that isn't available on their website and instead requires you
to contact them.

I hope I'm wrong since I have some ideas I'd like to try it out with. Sending
my customer's data to their cloud is probably a non-starter.

~~~
wiktor_walc
Recently we realised that our public communication about collaboration is
quite confusing ;( We mention "Cloud Services" everywhere, but the reality is
that you can have an onpremise installation of our collaboration backend that
you can host/control by yourself. The SAAS offer was first, that's why the
current website looks how it looks. The onpremise offer is currently in a
closed private-beta state, so if there is anyone willing to give it a try,
we're open. We'll make it fully public in a month or two, after we polish the
documentation and so on.

------
whitten
Is there any difference in editing a structured document which is intended to
ultimately be text for presentation and reading, versus a structured document
which is describing requirements for code or a storyboard for a design? Do
these different end-results change the collaborative environment?

~~~
taeric
I would think yes. Structured editing is tough because of the interaction
possibilities. Think of it in simplistic terms "add words to paragraph" at the
same time as "remove paragraph." What do you do?

With text presentation and reading, you are ultimately limiting the number of
things that can be seen that way. Though, you can of course expand your entity
list to include more and more things. Headers, lists, sections, chapters,
paragraphs, etc.

That is to say, I think this is already difficult for structured text. Adding
more structure, in the forms of "requirements section" and such just compounds
on that complication. I'm not sure it adds more.

------
galaxyLogic
What is the main use-case for this? I'm looking at it from a coder's
perspective. When I'm writing some code I wouldn't want somebody else
inserting characters into my code while I am editing it.

But I can see that if the app is divided into a multiple code-files then
different coders can be working on different files at the same time. Still I
prefer some form of code ownership or at least locking of multiple files just
for me while I'm working on them.

I don't quite see how it would be much different for other kinds of text.
While I'm writing this post right now I wouldn't want somebody else modifying
its beginning while I'm writing its end.

Not saying there aren't any good use-cases, just can't think of any right now.
So that's my question, what are they?

~~~
jmvoodoo
The typical way I've seen this used is almost like pair programming. One user
will write a draft of something, or add an image or chart while on a
conference call with the other editor(s). Honestly, I see it a lot more with
spreadsheets than with rich text, but the use case is there. It was one of the
features that put Google docs on the map back in the day.

------
badestrand
I can imagine real-time collaboration is an immensely interesting problem to
work on.

Also wonderful blog post, actually read it in full, thanks!

~~~
tabtab
If I were Google I'd buy up CKEditor to help compete with Microsoft Office.

~~~
chx
I do not think they are interested. Google Docs/Sheets gets features at a very
slow pace -- if Google wanted to compete with Office they could literally pour
hundreds of millions and a legion of developers into it. As the only
monetization I am aware of is Google Suite perhaps that's not enough to
justify it. Unless you want to see ads in Docs / Sheets... also, Google Wave
has been cancelled.

~~~
tabtab
Re: _Unless you want to see ads in Docs / Sheets_

The more you use a product, the more you visit related sites and materials on
the web; so yes, ads.

------
hardwaresofton
Recently saw a fantastic intermediate talk on this subject called CRDTs and
the Quest for Distributed Consistency[0]. One product of the research was
automerge[1], a library for handling collaborative editing of JSON-like data
models

[0]:
[https://www.youtube.com/watch?v=B5NULPSiOGw](https://www.youtube.com/watch?v=B5NULPSiOGw)

[1]:
[https://github.com/automerge/automerge](https://github.com/automerge/automerge)

------
dbcurtis
This is a great blog post.

It was interesting to see how they approached moving from a linear data model
to a tree structured data model. Is anyone aware of similar work with graph
structured data, as you find in electronic design automation? Think
collaborative schematic editing.

------
cjblomqvist
Nice writeup! A tiny nitpick, shareJS (DerbyJS) had/have an object based OT
implementation (ie. tree) since before this was started I think (or around the
same time).

~~~
scofalik
As far as I remember shareJS was available when we started to work on tree-
based OT. We researched it but it turned out to be too simple for what we
wanted to achieve and there was no special handling for some edge cases that
happens during collaborative editing.

We achieved something similar to shareJS functionality quite early, to be
honest. What proved to be extremely difficult was all the extras to smooth up
the user experience. We would have to (heavily) extend shareJS anyway, so it
made more sense to go out with own solution, crafted for our needs.

------
amelius
> We started building our next generation rich-text editor with the assumption
> that real-time collaborative editing must be the core feature that lies at
> its very foundation

Am I the only one who doesn't like other people typing through my work? Why
not simply let the user choose when to merge their work with others?

Honestly, sometimes I feel collaborative text editors have been created "just
because we can" or "just because we want to see if we can".

~~~
codebeaker
if jira and confluence allowed this my company would benefit from probably a
double digit efficiency boost.

we have to split our "collaborating" to google docs, and our "carving in
stone" in JIRA and Confluence.

I'll say though that the "suggested edit" and "comment on a range" features
(and the distinct edit modes about commenting, suggesting and approving edits,
and free for all battle royale are all valid modes for us all the time.) (300
person SF+intl. software company)

~~~
negativegate
Doesn't Confluence have collaborative editing?
[https://confluence.atlassian.com/doc/collaborative-
editing-8...](https://confluence.atlassian.com/doc/collaborative-
editing-858771779.html)

------
ianstormtaylor
How do you keep track of the nodes in the "graveyard"? Does that mean that
each node has to have some sort of UUID across clients?

~~~
scofalik
Graveyard is just another root, like the main one. So, the same way that all
elements have the same position in the main root for all clients, elements in
graveyard also have the same position for all clients. Thus, their path is
kind of UUID for them.

------
codetrotter
The link at the bottom which said that you could check out a demo was
confusing because there was no demo there.

Demo can be found at
[https://ckeditor.com/docs/ckeditor5/latest/features/collabor...](https://ckeditor.com/docs/ckeditor5/latest/features/collaboration/overview.html)

~~~
scofalik
It seems that the link is fine. Scroll a little down and you can test the
collaboration in Letters (built using CKE5) or with CKE5 document build
(switch the tab).

~~~
codetrotter
I should note that I am on mobile. On mobile I don’t see a demo in the link
from the OP whereas the demo in the link I posted above is available on
mobile.

~~~
wiktor_walc
Yes, that's correct. The demo for mobiles is intentionally hidden because both
examples on ckeditor.com are right-now desktop-like. We'd be working soon on a
solution that would provide much better UX for mobiles, once we do it we'd
show a dedicated demo for mobile devices.

------
Tade0
Nice write-up. I've seen[0] the blood, sweat and tears that went into this
project and I have to say it has come a long way.

BTW any timeline on sunsetting the venerable CKEditor 4?

[0] I was part of the CKEditor 4 team back when the CKE5 guys were laying down
some the first iterations of what is described in this blog post.

~~~
wiktor_walc
Hey Tade0! As much as we love CKEditor 5 that we created, we also love our
users who are still widely using CKEditor 4. Some of them invested many, many
months to create custom plugins, adopt CKEditor to their systems and so on.
So, being a responsible company, we will maintain this product still for
several years. As a company that creates components, which are embed into
other systems, we have to simply deliver stuff that others, including big
enterprise customers, can rely on. I know it's a bit unusual in JavaScript
world to maintain software for 8(!) or even more years, but this is what we
do. Yes, we're a bit crazy.

------
js4ever
This is a disguised ad for their saas offer. Seems interesting but no public
pricing. Meaning it's probably very expensive and targeting big customers.

------
shyamala
It is clear that Google Docs is using OT.Curious to know what Office365 is
using for its real-time collaboration.

------
stuaxo
This is pretty interesting, would like to apply it to other kinds of editor.

These abstractions should be in the OS really.

------
bawana
I dont understand why this is so hard. If you take a document and enter each
character into a database as a separate entry, then only lock each character
as it's changed and unlock it immediately afterwards. The likelihood that all
individuals will be modifying the same character at the same time is low. and
while it's locked, the person trying to change it will see it's not changing -
so they'll try again in a second or two by which time it will be unlocked.

~~~
jerf
Among the many other problems with your proposal, you are assuming an editor
that can only insert and delete characters, so no selection, copy, paste,
search and replace, and any other features that involve modifying more than
just one character in a document at a time, since you're critically depending
not just on the fact that all edits can theoretically be represented by single
character changes but that the rate of such changes must necessarily be very,
very low, bounded by human typing speed.

"OK, so to fix that, I'll just..."

That'll break in some other case. If you then work on fixing that up, in
another 20 or 30 steps, you end up at these algorithms. Or something far
worse, which is actually pretty likely if you try to bodge something together
one hyper-local problem at a time.

~~~
Skunkleton
No, op is assuming that an editor can only _replace_ characters.

