For the complete documentation index, see llms.txt. This page is also available as Markdown.

Learn More About Document Collaboration in WebViewer

WebViewer's JavaScript document collaboration library contains APIs that allow you to export/import annotations from/to a document. Using those APIs and a server, you can set up realtime collaboration easily.

Apryse does not ship any server side collaboration tools - you must take the basic concepts outlined below and use them to implement your own flow within your application.

Technologies

Enabling collaboration in WebViewer requires you to build a server that can sync annotations back and forth between users. This typically involves storing annotation data (XFDF) in a database and enabling some kind of real-time connection between your clients and your server. This is typically accomplished through the use of Web Sockets.

You can use any backend technologies you wish. We provide samples using SQLite and Firebase, but collaboration is not restricted to these technologies.

Collaboration basics

Syncing annotations (client side)

Setting up real time collaboration typically involves binding to the WebViewer annotationChanged event, and syncing the clients annotation state with your servers annotation state.

This usually will look something like this

WebViewer(...)
  .then(instance => {
    const { annotationManager } = instance.Core;
    annotationManager.addEventListener('annotationChanged', (annotations, action) => {
      
      // It is recommended to assign a unique ID to each document
      const documentId = getDocumentId()
      
      // Sync annotations with server depending on the action
      if (action === 'add') {
        await addAnnotations(annotations, documentId)
      } else if (action === 'modify') {
        await modifyAnnotations(annotations, documentId)
      } else if (action === 'delete') {
        await deleteAnnotations(annotations, documentId)
      }
    });
  }))

The addAnnotations, modifyAnnotations, and deleteAnnotations functions will typically contain your own logic to extract the XFDF from the changed annotations and push the updates to your server.

Here's an example of what an addAnnotation function might look like.

It is recommended to assign a unique ID to each document in your system. This will allow you to easily fetch and sync annotations on a per-document basis.

You should generate these ID's with your own system instead of using the ID generated by WebViewer.

Syncing annotations (server side)

Once you have your client sending XFDF data to your server, you need to update your server to handle that data. This will typically involve setting up endpoints for each annotation operation (add, modify, delete).

Each of these endpoints should have 3 primary functions:

  1. Authenticate the user

  2. Sync the annotation to the database

  3. Send real-time updates to other connected users

User authentication will depend on your server technology, so that will not be explained in this guide.

Syncing the annotation to your database will usually mean writing the XFDF, the userId, the documentId, and an annotationId.

If you are using an ORM like Prisma, this could look like this:

The same logic applies for modifying data, except instead of writing a new row to your database, you will be editing or deleting an existing row.

Real-time syncing between users

Once you have your basic annotation sync in place, you can start implementing the real-time updates between users.

There are many strategies you can use to accomplish this, but the most common are

If possible, we recommend using WebSockets as they provide a true real-time user experience.

The general strategy to implementing real-time updates is as follows

  1. Each client that is viewing a document subscribes to a "topic", usually identified by the document ID

  2. Any time your server receives a request to add/edit/delete annotations, it pushes an event to that topic. The payload for the event should contain the updated XFDF. These events should then fan out to your clients.

  3. When your client receives an event from the server, it should take the payload and use WebViewer APIs to sync the new annotation with the viewer

Here is a code sample using socket.io to show what this might look like:

Loading annotations on document load

The final piece of functionality for a basic real-time collaboration flow is displaying a document's annotations on load.

This is done by querying all the annotations belonging to the document from your database, and importing the XFDF for those annotations into WebViewer.

Here is an example of what this might look like:

Next steps

The rest of the guides in this section walk you through how to implement a real-time collaboration flow using Firebase using the same concepts we discussed above.

Get started by setting up your viewer.

If you are not using firebase, we still recommend reading the remaining guides as the same concepts with almost any technology stack.

Last updated

Was this helpful?