Skip to content

Latest commit

 

History

History
252 lines (162 loc) · 10.2 KB

cloud.md

File metadata and controls

252 lines (162 loc) · 10.2 KB
tableOfContents
true

Tiptap Collab

Implementing real-time collaboration is quite hard. With Tiptap Collab we build a solution that does it in minutes. To see it in action check out our live demo.

Tiptap Collab is our managed cloud solution of Hocuspocus. It makes it a easy to add real-time collaboration to any application. If you already have an application using Tiptap Editor, it's even easier to add collaboration.

:::warning Pro Feature To get started, you need a Tiptap Pro account. Log in or sign up for free. :::

Getting Started

Installation

First you need to install @hocuspocus/provider at least in version 2.0.0.

npm install @hocuspocus/provider

Basic Usage

Tiptap Collab makes your application collaborative by synchronizing a Yjs document between connected users using websockets. If you're already using Yjs in your application, it's as easy as this:

import { TiptapCollabProvider } from '@hocuspocus/provider'
import * as Y from 'yjs'

const provider = new TiptapCollabProvider({
  appId: 'your_app_id', // get this at collab.tiptap.dev
  name: 'your_document_name', // e.g. a uuid uuidv4();
  token: 'your_JWT', // see "Authentication" below
  document: new Y.Doc() // pass your existing doc, or leave this out and use provider.document
});

Upgrade From Hocuspocus

If you are upgrading from our self-hosted collaboration backend called Hocuspocus, all you need to do is replace HocuspocusProvider with the new TiptapCollabProvider. The API is the same, it's just a wrapper that handles the hostname to your Tiptap Collab app and authentication.

Example

Cloud Documents

We have created a simple client / server setup using replit that you can review and fork here:

Github or Replit Demo

The example loads multiple documents over the same websocket (multiplexing), and shows how to implement per-document authentication using JWT.

More tutorials can be found in our Tutorials section.

Authentication

Authentication is done using JSON Web Token (JWT). There are many libraries available to generate a valid token.

JWT Generation

To generate a JWT in the browser, you can use http://jwtbuilder.jamiekurtz.com/. You can leave all the fields as default, just replace the "Key" at the bottom with the secret from your settings.

In Node.js, you can generate a JWT like this:

import jsonwebtoken from 'jsonwebtoken'

const data = {
  // Use this list to limit the number of documents that can be accessed by this client.
  // An empty array means no access at all.
  // Not sending this property means access to all documents.
  // We are supporting a wildcard at the end of the string (only there).
  allowedDocumentNames: ['document-1', 'document-2', 'my-user-uuid/*', 'my-organization-uuid/*']
}

// This JWT should be sent in the `token` field of the provider. Never expose 'your_secret' to a frontend!
const jwt = jsonwebtoken.sign(data, 'your_secret')

Webhook

You can define a URL and we will call it every time a document has changed. This is useful for getting the JSON representation of the Yjs document in your own application. We call your webhook URL when the document is saved to our database. This operation is debounced by 2-10 seconds. So your application won't be flooded by us. Right now we're only exporting the fragment default of the Yjs document. You can add the webhook URL in the settings page of your Tiptap Collab app.

Payload

A sample payload of the webhook request looks like this:

{
  "appName": '', // name of your app
  "name": '', // name of the document
  "time": // current time as ISOString (new Date()).toISOString())
  "tiptapJson": {}, // JSON output from Tiptap (see https://tiptap.dev/guide/output#option-1-json): TiptapTransformer.fromYdoc()
  "ydocState"?: {}, // optionally contains the entire yDoc as base64. Contact us to enable this property!
  "clientsCount": 100 // number of currently connected clients
}

Signing

All requests to your webhook URL will contain a header called X-Hocuspocus-Signature-256 that signs the entire message with your secret. You can find it in the settings of your Tiptap Collab app.

Management API

In addition to the websocket protocol, each Tiptap Collab app comes with a REST API for managing your documents. It's exposed directly from your Tiptap Collab app, so it's available at your custom URL:

https://YOUR_APP_ID.collab.tiptap.cloud/

Authentication is done using an API secret which you can find in the settings of your Tiptap Collab app. The secret must be sent as an Authorization header.

If your document identifier contains a slash (/), just make sure to encode it as %2F, e.g. using encodeURIComponent of vanilla JavaScript.

Create Document

POST /api/documents/:identifier

This call takes a binary Yjs update message (an existing Yjs document on your side must be encoded using Y.encodeStateAsUpdate) and creates a document. This can be used to seed documents before a user connects to the Tiptap Collab server.

This endpoint will return the HTTP status 204 if the document was created successfully, or 409 if the document already exists. If you want to overwrite it, you must delete it first.

curl --location 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/DOCUMENT_NAME' \
--header 'Authorization: YOUR_SECRET_FROM_SETTINGS_AREA' \
--data '@yjsUpdate.binary.txt'

List Documents

GET /api/documents

This call returns a list of all documents present on the servers storage.

curl --location 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents' \
--header 'Authorization: YOUR_SECRET_FROM_SETTINGS_AREA'

Get Document

GET /api/documents/:identifier?format=:format&fragment=:fragment

This call exports the given document with all fragments in JSON format. We export either the current in-memory version or the version read from the database. If the document is currently open on your server, we will return the in-memory version.

format supports either yjs or json. Default: json

If you choose the yjs format, you'll get the binary Yjs update message created with Y.encodeStateAsUpdate.

fragment can be an array (fragment=a&fragment=b) of or a single fragment that you want to export. By default we'll export all fragments. Note that this is only taken into account when using the json format, otherwise you'll always get the whole Yjs document.

curl --location 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/DOCUMENT_NAME' \
--header 'Authorization: YOUR_SECRET_FROM_SETTINGS_AREA'

Note: When using axios, you need to specify responseType: arraybuffer in the options of the request.

const ydocUpdate = await axios.get('https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/somedoc?format=yjs', { responseType: 'arraybuffer' })

Update Document

PATCH /api/documents/:identifier

This call accepts a Yjs update message and will apply it on the existing document on the server. This endpoint will return the HTTP status 204 if the document was updated successfully, 404 is the document does not exist, or 422 if the payload is invalid or the update cannot be applied.

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/DOCUMENT_NAME' \
--header 'Authorization: YOUR_SECRET_FROM_SETTINGS_AREA' \
--data '@yjsUpdate.binary.txt'

Delete Document

DELETE /api/documents/:identifier

This endpoint deletes a document from the server after closing any open connection to the document.

It returns either HTTP status 204 if the document was deleted successfully or 404 if the document was not found.

curl --location --request DELETE 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/DOCUMENT_NAME' \
--header 'Authorization: YOUR_SECRET_FROM_SETTINGS_AREA'

Duplicate Document

In order to copy a document, you can just use the GET endpoint and then create it again with the POST endpoint, here's an example in typescript:

const docUpdateAsBinaryResponse = await axios.get('https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/somedoc?format=yjs', {
  headers: {
    'Authorization': 'your_token',
  },
  responseType: 'arraybuffer',
})

await axios.post('https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/somedoc-duplicated', docUpdateAsBinaryResponse.data, {
  headers: {
    'Authorization': 'your_token',
  },
})

Screenshots

Here are some screenshots of Tiptap Collab to give you an idea what of Tiptap Collab looks like.

Dashboard

View key metrics such as total or concurrent connections of your Tiptap Collab app.

Cloud Dashboard

Documents

Get insight into all your documents, such as size or delete them if you want.

Cloud Documents

Logging

View real-time log events for information about currently loaded or modified documents.

Cloud Settings

Settings

Manage the authentication of your application or defined webhooks in the settings.

Cloud Settings

Need anything else?

Contact us on Discord or send an email to humans@tiptap.dev.