Report an issue

guideReal-time collaborative editing

The RealTimeCollaborativeEditing plugin is the base of real-time collaboration in CKEditor 5. It allows for editing the same document by multiple users at the same time. It also shows the selection of other users in real time and automatically solves all conflicts.

Collaborative selection design in CKEditor 5 WYSIWYG editor.

# Installation

Since collaboration features are not included in any default build, to use real-time collaborative editing you need to have a custom build which will include the RealTimeCollaborativeEditing plugin. You can use one created in the quick start guide or learn more about installing plugins and prepare your custom build.

Complementary to this guide, we provide ready-to-use samples available for download. We prepared samples for all editor types (multi-root included) as well as for the React integration. You may use them as an example or as a starting point for your own integration.

When your build with real-time collaboration feature is ready, you can update the sample and add CKEditor Cloud Services configuration to it:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>CKEditor 5 Collaboration – Hello World!</title>
    </head>

    <div id="editor"></div>

    <script src="../build/ckeditor.js"></script>
    <script>
        ClassicEditor.create( document.querySelector( '#editor' ), {
            initialData: '<p>Let\'s edit this together!</p>',
            toolbar: [ 'bold', 'italic', 'imageUpload' ],
            plugins: [ 'Essentials', 'Paragraph', 'Bold', 'Italic', 'EasyImage', 'RealTimeCollaborativeEditing' ],
            cloudServices: {
                // PROVIDE CORRECT VALUES HERE:
                tokenUrl: 'https://example.com/cs-token-endpoint',
                uploadUrl: 'https://your-organization-id.cke-cs.com/easyimage/upload/',
                webSocketUrl: 'your-organization-id.cke-cs.com/ws/',
                documentId: 'collabEditing'
            }
        } )
        .catch( error => console.error( error ) );
    </script>
</html>

If you do not have your CKEditor Cloud Services URLs yet, read more about them in the CKEditor Cloud Services Collaboration - Quick Start guide.

# Integration

When your collaborative document is up and running, it is time to think about the integration with your application.

Do note that CKEditor Cloud Services does not save or load the document content. It is a medium to handle the collaboration process. Content management should be handled by the integrated application.

# Data initialization

At this point, you should have a basic understanding of all configuration options you pass to the editor configuration, except the documentID property.

The documentID is a very important property when you collaborate. It tells CKEditor Cloud Services which editor instances should collaborate. All editor instances created with the same document ID will collaborate. It means that each document needs a different document ID if you do not want to start collaboration between these documents. The ID is usually a primary key of the document in the database, but you are free to provide whatever identifier fits your scenario. The documentID needs to be unique in the environment so if you are using, for instance, staging and production environments, you may use the same document ID. Since the environments are separated, they will not collaborate with each other.

When the first user with a certain document ID opens the rich-text editor, their content is sent to CKEditor Cloud Services. In case of the example above it is:

<p>Let's edit this together!</p>

Then, when the next user connects to the same document, they get the content from CKEditor Cloud Services. Their local content does not matter as long as there is already an existing document with connected users. The document is removed from CKEditor Cloud Services a while after the last user disconnects.

This is the reason why you should not use editor.setData() or editor.data.set() methods when using the collaboration plugin. The content of the editor needs to be defined before the editor initialization, so the collaboration plugin can decide which data should be used. Use the initialData configuration option instead.

Keep in mind that editor.setData() and editor.data.set() simply overwrite the content of the editor. The entire existing content is removed and the new content is loaded, even if it is the same. In collaboration, this behavior can cause issues. All client local data will be overwritten, which means that some data might be lost. In most cases, using editor.setData() and editor.data.set() in real-time collaboration is a mistake either in the integration or a third-party plugin. For that reason, the editor throws an error when this is attempted.

If you are sure that you understand and accept the behavior and effects of setting the data in this way, use editor.data.set() with the flag suppressErrorInCollaboration set to true, for example:

editor.data.set( '<p>Your data</p>', { suppressErrorInCollaboration: true } );

This will let you overwrite the editor data without throwing an error.

Note that to start the collaboration on a new document, you need the document ID from the very beginning, when the editor is created for the first time. If your application creates document IDs later, for instance when the form is submitted, you may need to work around this issue by creating a mapping between the editor document IDs and your application IDs.

# Saving data

The document is temporarily stored in the cloud by CKEditor Cloud Services only when there are connected users. It means that when the last user disconnects, the content should be saved in the database on your server.

Note that CKEditor 5 will handle the real-time synchronization of the content in the editor between collaborating clients. You need to take care of the collaborative workflow in the rest of your application. For instance, if the editor is a part of the bigger data form, you need to take care to make the whole form collaborative. The classic data form with the “Save” button might not work for you since the data will not be saved in real time in your database even if the editor will synchronize the content between all your clients. It is recommended to save the data automatically whenever it changes.

CKEditor provides two utilities to make your integration simpler.

# The cloudDocumentVersion property

The first helper is the cloudDocumentVersion property. When your collaborative users are saving the same document at the same time, there might be a conflict. Especially it might happen that older document overwrites the new one.

To prevent race conditions, the cloudDocumentVersion variable is provided:

editor.plugins.get( 'RealTimeCollaborationClient' ).cloudDocumentVersion

It is a number that defines which client has a newer version of the document. This number should be stored in the database together with the content. When any client wants to save the content, document versions should be compared. The document should only be saved when the version is higher. Otherwise, it means that this is an older version of the document and there is already a newer version saved.

The cloudDocumentVersion is stored in the CKEditor Cloud Services server between collaboration sessions so if you start a new session, this property will equal the number it reached at the end of the previous session. It also means that cloudDocumentVersion is equal to editor.model.document.version only during the first collaboration session on the given document. For the next sessions, editor.model.document.version will start counting from 0 while cloudDocumentVersion will be higher.

# The Autosave plugin

The second helper is the Autosave plugin.

The autosave plugin triggers the save callback whenever the user changes the content. It takes care of throttling the callback execution so it is not called too often. It also automatically secures the user from leaving the page before the content is saved.

The autosave plugin is not included in any of the builds by default nor automatically required by the real-time collaboration plugins so you need to install it separately. To learn more about this plugin refer to the Getting and saving data guide.

# Users selection

The collaborative editing feature not only synchronizes the document content between all participants, but it also shows each user the selection of all other users in real time. It works out of the box and does not require any additional configuration. This is the only part of the collaborative editing plugin that provides a UI. See the Users in real-time collaboration guide to learn more.