Important changes to Tiny Cloud pricing > Find out more

RTC configuration

List of all available RTC configuration options.

Contribute to this page

Important: The Real-Time Collaboration beta is invite only. For information on joining the beta, visit the RTC beta access page.

Note: These configuration options is subject to change based on customer feedback.

Required options

The following options are required for the RTC plugin:

rtc_document_details_provider

The document details include a document ID. This is the ID users share with other people collaborating on the document.

Type: Function

Required: yes

Return fields for rtc_document_details_provider

Field Type Description
documentId string Unique identifier for the document. In a content management system, this could be the resource identifier for the document.

Example Using the document details provider to return static document details

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_document_details_provider: () => {
    return Promise.resolve({ documentId: "your-document-id" })
  }
})

Example Using the document details provider to return document details from your server

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_document_details_provider: () => {
    return fetch('http://yourserver/getDocumentId', {
      method: 'POST'
    })
    .then(documentId => ({ documentId });
  }
})

rtc_encryption_provider

The RTC plugin requires a generated key to encrypt messages for end-to-end encryption. This key not sent to the Tiny Cloud, preventing the TinyMCE RTC service from reading the editor content. The encryption key is used by the user’s browser to encrypt and decrypt the editor content between users.

To generate a unique encryption key, create a function that accepts the following arguments:

  • The document ID
  • The session ID
  • A key hint (only required for existing sessions)

Secure ways to generate an encryption key include:

  • Generate and store a random key for each new document session in your database.
  • Generate single random key per document, and salt it on your server with the session ID to provide a different key per session.
  • Store a global list of keys for your application, and use the document ID and session ID to salt the current key on your server to produce a key unique to the document session. You should return a key hint to identify the key in case you rotate to a new key later.

Type: Function

Required: yes

Input fields for rtc_encryption_provider

Field Type Description
documentId string Unique public document ID that is used when sharing the document.
sessionId integer Session ID generated by the server. This should be a number between 0 and 2147483648 (231).
keyHint string or undefined Key hint (such as a key ID) provided by the client which opened the session (only required if there is an existing session).

Return fields for rtc_encryption_provider

Field Type Description
key string Encryption key that is used to locally encrypt operations. This key needs to be the same for all connecting clients.
keyHint string or undefined Optional key hint to provide to clients that connect later, to aid in key selection. This can be a key thumbprint, ID or other non-sensitive identifier that will help select the key like a timestamp. It is only recorded when opening a new session. (unicode, max 256 characters)

Example of providing static encryption details

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_encryption_provider: ({documentId, sessionId}) => {
    return Promise.resolve({
      key: "your shared encryption key"
    });
  }
})

Example of providing encryption details from your server

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_encryption_provider: ({documentId, sessionId, keyHint}) => {
    return fetch('http://yourserver/getKey', {
      method: 'POST',
      body: JSON.stringify({ documentId, sessionId, keyId: keyHint })
    })
    .then(({keyId, secret}) => ({ key: secret, keyHint: keyId });
  }
})

rtc_token_provider

The RTC plugin and service uses JWT to authenticate the user. This token should include a unique user ID and a relative expiration time. This provider function will be called multiple times to refresh the token if it’s about to expire. For production usage, the token provider should be a dynamic request that produces a new JWT token with an updated exp claim.

Type: Function

Required: yes

Required JWT claims

Field Type Description
sub string The unique user ID (If sub is the same for two clients, the server should trust them as if they are the same user).
exp integer The timestamp when the token expires.

Return fields for rtc_token_provider

Field Type Description
token string A generated JWT token. This token should be signed with the private key.

Example of providing a static JWT token

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_token_provider: () => Promise.resolve({ token: "your-jwt-token" })
})

Example of providing a JWT token from your server

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_token_provider: () => {
    return fetch('http://yourserver/getJwtToken', {
      method: 'POST'
    })
    .then(token => ({ token });
  }
})

rtc_snapshot

Real-time collaboration sessions don’t typically have a save button and the session is constantly being stored. A snapshot callback will be executed at regular intervals with the serialized editor content. The content is retrieved though a getContent function to lazily create the serialized version of the content to reduce the CPU load.

Type: Function

Required: no

Input fields for rtc_snapshot

Field Type Description
sessionId integer Session identifier generated by the server. This should be a number between 0 and 2147483648 (231).
version integer An increasing version number between 0 and 2147483648 (231).
getContent() string Function to execute to get the content for that particular version.

Example of getting content snapshots

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_snapshot: ({sessionId, version, getContent}) => {
    console.log('Current version', version);
    console.log('HTML', getContent());
  }
}

rtc_initial_content_provider

By default, the initial editor content is retrieved from the target element, as specified using the selector option. The RTC plugin provides the rtc_initial_content_provider option to allow the initial content be retrieved for a new RTC session. This also works with the various TinyMCE integrations that don’t provide access to the target element directly.

Type: Function

Required: no

Return fields for rtc_initial_content_provider

Field Type Description
content string String containing the HTML to be imported into the editor when there is no active session.

Example of providing static content

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_initial_content_provider: () => Promise.resolve({ content: "<p>Hello world!</p>" })
})

Example of providing dynamic content from the server

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_initial_content_provider: () => {
    return fetch('http://yourserver/getContent', {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      }
    });
  }
})

rtc_user_details_provider

By default, the user ID will be displayed as the name on remote carets shown in the editor when there are active collaborators on the editor content. To display an alternative name on the caret, the user ID needs to be resolved into user details that include the full user name. This provider function will be called for each connecting client. If this option is omitted, the user ID will be presented as the name for the remote user, when a user hovers over the remote carets.

Only userId is guaranteed to be authentic as it comes from the JWT. Tiny suggests using userId to fetch the user data from your server to guarantee authenticity.

Type: Function

Required: no

Input fields for rtc_user_details_provider

Field Type Description
userId string User ID to resolve into user details.

Return fields for rtc_user_details_provider

Field Type Description
fullName string Full name of user. For example: "John Doe".

Example of providing static user details

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_user_details_provider: ({userId}) => Promise.resolve({ fullName: "John Doe" })
})

Example of providing user details from your server

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_user_details_provider: ({userId}) => {
    return fetch('http://yourserver/getUserDetails', {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({userId})
    });
  }
})

rtc_custom_user_details

The rtc_custom_user_details option allows extra details to be provided about the current user to the other connecting clients. This option should not be used to communicate sensitive information; the authenticity of user data cannot not guaranteed.

This API is designed for use in status flags such as “is the user on a mobile device”.

This option accepts an object that must be serializable (JSON.stringify will be used to transmit it between clients).

Type: Object

Required: no

Example of providing custom user details

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_custom_user_details: { onMobile: true, region: 'us' }
})

rtc_user_connected

This option allows applications to show when a user enters the RTC session. There are 8 distinct caret colors (given a value from 1 to 8). If more than 8 people connect to a session, the numbers will be reused. This is useful for keeping a list or array of connected users up-to-date.

Type: Function

Required: no

Input fields for rtc_user_connected

Field Type Description
userId string This is the JWT user ID of the connecting user.
caretNumber integer The user’s caret number 1-8 (helpful to disambiguate when a user connects multiple times).
custom object Custom data passed out from the other clients rtc_custom_user_details function. If none are provided, this will be an empty object.

Example of providing custom user details for rtc_user_connected

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_user_connected: ({userId, caretNumber, custom}) => {
    console.log('Connected', userId, caretNumber, custom);
  }
})

rtc_user_disconnected

This option allows applications to track when a user leaves the session. This is useful for keeping a list or array of connected users up-to-date.

Type: Function

Required: no

Input fields for rtc_user_disconnected

Field Type Description
userId string This is the unique user ID of the disconnecting user.
caretNumber integer The user’s caret number 1-8 (helpful to disambiguate when a user connects multiple times).
custom object Custom data passed out from the other clients rtc_custom_user_details function. If none are provided, this will be an empty object.

Example of providing custom user details for rtc_user_disconnected

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'rtc',
  rtc_user_disconnected: ({userId, caretNumber, custom}) => console.log('Disconnected', userId, caretNumber);
})

Can't find what you're looking for? Let us know.

Except as otherwise noted, the content of this page is licensed under the Creative Commons BY-NC-SA 3.0 License, and code samples are licensed under the Apache 2.0 License.