Skip to main content

Get started

Welcome to WebViewer Collaboration! This guide will walk you through getting WebViewer Collaboration integrated into an application. Before starting implementation, it is recommended to read the core concepts guide to get a grasp of how these modules work at a high level.

The source code for this guide is available here, but we recommend following along to learn some core concepts.

This guide will assume that you already have an application using WebViewer, and also assumes you have Docker installed on your machine. We will be using Docker to set up a database.

info

This guide is intended to show you the basics of WebViewer Collaboration. The code is not production grade!

Setting up the database#

In this guide we will be setting up a new database to store collaboration related data. If you already have a database with existing data, check out the integrating with an existing database guide.

WebViewer Collaboration comes with a Postgres database you can use to quickly get started collaborating.

Installing the module#

Start by installing the database module by running yarn add @pdftron/collab-db-postgresql.

Now that the module is installed, we can use the provided scripts to start the Docker container and install a local PostgreSQL database.

Start up the database#

Navigate into the modules directory by running

cd node_modules/@pdftron/collab-db-postgresql

We now have access to the pre-configured scripts provided by the module.

Start up the PostgreSQL database by running

yarn start-local-db --name collab --password pdftron

The name parameter is what we want our docker container to be called, and password will be our databases master password (feel free to change these values). View all the available parameters here.

Initialize the database#

Now that our database is up and running, we need to create all the tables required for Collaboration to work. We also provide a script for this!

Run the following command to initialize and seed the database:

yarn init-db --password pdftron --dbName collab

The password parameter is the password we set in the previous step, and dbName will be the name of the newly created database. View all the available parameters here.

After running this command, our database is ready to go!

Setting up the server#

The next step to implementing WebViewer Collaboration is setting up the server. Now that we have our database set up, this part is very easy.

First, install the server module by running yarn add @pdftron/collab-server.

info

In order to use the server, we need to have the COLLAB_KEY environment variable set. Read this guide for instructions on doing so.

If you do not already have a node server, you can create one by creating a server.js in your project. If you do already have a node server, do the following steps inside your existing server.

Import both the server module and the database module:

const CollabServer = require('@pdftron/collab-server');
const CollabDatabase = require('@pdftron/collab-db-postgresql');

Now we can configure the database module to connect to the database we created in the last step. Add this code to the top of your server file:

const CollabServer = require('@pdftron/collab-server');
const CollabDatabase = require('@pdftron/collab-db-postgresql');
const db = new CollabDatabase({
host: '127.0.0.1',
port: 5432,
dbName: 'collab', // This is the dbName we set in the previous step
username: 'postgres',
password: 'pdftron' // This is the db password we set in the previous step
});
(async () => {
await db.connectDB();
})()

Now we're ready to initialize the server. Add the following code to your server:

const CollabServer = require('@pdftron/collab-server');
const CollabDatabase = require('@pdftron/collab-db-postgresql');
const db = new CollabDatabase({
host: '127.0.0.1',
port: 5432,
dbName: 'collab', // This is the dbName we set in the previous step
username: 'postgres',
password: 'pdftron' // This is the db password we set in the previous step
});
(async () => {
await db.connectDB();
const server = new CollabServer({
resolvers: db.getResolvers(),
// Allow requests from all domains
corsOption: {
origin: true
}
})
server.start(3000);
})()

The db.getResolvers() function returns a set of default resolvers for the server to use. Resolvers are the functions that allow WebViewer Collaboration to read and write from your database.

That's it! When you start up your server, you should see a log like this:

Setting up the client#

Now that our server and database are up and running, we are ready to set up the client.

First, install the client module with yarn add @pdftron/collab-client

note

If you do not have a WebViewer project already, you can create one by following the WebViewer get started guide. Once you have a project set up, come back to this guide!

Find the place in your codebase where you are initializing the WebViewer library - this is where we will also initialize the collaboration client.

The WebViewer initialization code will look something like this:

import WebViewer from '@pdftron/webviewer'
WebViewer(
{
path: '/lib/webviewer'
},
document.getElementById('viewer')
).then(async instance => {
});

Import the Collaboration client and initialize it in the promise returned from WebViewer:

import WebViewer from '@pdftron/webviewer'
import { CollabClient } from '@pdftron/collab-client'
WebViewer(
{
path: '/lib/webviewer'
},
document.getElementById('viewer')
).then(async instance => {
const client = new CollabClient({
instance,
url: `http://localhost:3000`,
subscriptionUrl: `ws://localhost:3000/subscribe`
})
});

The url and subscriptionUrl are the URLs of the server we set up in the previous step. In the screenshot above you will notice that these values are logged by the server when starting up. We also pass the WebViewer instance.

That's all we need to do to initialize the client!

Logging in a user#

The first step to using the client library is logging in a user.

For this example, we will be using anonymous users.

note

WebViewer Collaboration also supports SSO for logging in users from an existing system. For a complete authentication flow (signing users in with access tokens or username and passwords), see this guide.

To log in an anonymous user, we use the client.loginAnonymously function and provide it a username to give to the user.

import WebViewer from '@pdftron/webviewer'
import { CollabClient } from '@pdftron/collab-client'
WebViewer(
{
path: '/lib/webviewer'
},
document.getElementById('viewer')
).then(async instance => {
const client = new CollabClient({
instance,
url: `http://localhost:3000`,
subscriptionUrl: `ws://localhost:3000/subscribe`
})
const user = await client.loginAnonymously('PDFTron');
});

All login functions resolve with a User, which will we use throughout the rest of the application.

Creating a document#

Next, we need to create a Document for the user to Collaborate on.

We can use the User.createDocument API to create a document.

We are going to write a function that creates a document for the current user, and call this function when some button is clicked in our UI.

import WebViewer from '@pdftron/webviewer'
import { CollabClient } from '@pdftron/collab-client'
WebViewer(
{
path: '/lib/webviewer'
},
document.getElementById('viewer')
).then(async instance => {
const client = new CollabClient({
instance,
url: `http://localhost:3000`,
subscriptionUrl: `ws://localhost:3000/subscribe`
})
const user = await client.loginAnonymously('PDFTron');
const filePath = 'https://pdftron.s3.amazonaws.com/downloads/pl/webviewer-demo.pdf';
const createDocument = async () => {
const document = await user.createDocument({
document: filePath,
isPublic: true,
name: 'document.pdf'
});
await document.view(filePath);
}
document.getElementById('my-button').onclick = createDocument;
});

In the code above, we are using a hard-coded URL for our document's location. In a real application, the user would probably upload a file or provide their own URL to the file. See creating documents for more info.

We also provide name for the document, and we also mark the document as public. See this guide for more details about public documents.

We then call the Document.view() function, which loads the document in WebViewer.

Now, when my-button is clicked, a document will be created and loaded in the viewer.

Listing documents#

In addition to creating documents, we may also want to get a list of a users documents to display somewhere in our UI. There are a couple ways to do this.

In this example we will skip the UI part and just use the list of documents to join and/or view them.

Getting a users documents

You can get the documents a user belongs to by using the User.getAllDocuments API. View other ways to get a users documents here.

Add the following code to your app:

import WebViewer from '@pdftron/webviewer'
import { CollabClient } from '@pdftron/collab-client'
WebViewer(
{
path: '/lib/webviewer'
},
document.getElementById('viewer')
).then(async instance => {
const client = new CollabClient({
instance,
url: `http://localhost:3000`,
subscriptionUrl: `ws://localhost:3000/subscribe`
})
const user = await client.loginAnonymously('PDFTron');
const filePath = 'https://pdftron.s3.amazonaws.com/downloads/pl/webviewer-demo.pdf';
const createDocument = async () => {
const document = await user.createDocument({
document: filePath,
isPublic: true,
name: 'document.pdf'
});
await document.view(filePath);
}
document.getElementById('my-button').onclick = createDocument;
const documents = await user.getAllDocuments();
if(documents.length > 0) {
const mostRecentDocument = documents[0];
await mostRecentDocument.view(filePath);
}
});

The code we just added grabs all the users documents, and loads the latest one in the viewer when the application loads. Here you could also loop over these documents and render them to your UI (see a React sample here).

Joining documents#

In order for a user to annotate a document, they must become a member of that document. This can accomplished a couple ways, but in this example we will just use the Document.join API.

note

Only public documents can be self-joined

For this example we will set up our app so that all users automatically join all public documents when they sign in.

Let's add some code to get the latest public document, and join them it we haven't already:

import WebViewer from '@pdftron/webviewer'
import { CollabClient } from '@pdftron/collab-client'
WebViewer(
{
path: '/lib/webviewer'
},
document.getElementById('viewer')
).then(async instance => {
const client = new CollabClient({
instance,
url: `http://localhost:3000`,
subscriptionUrl: `ws://localhost:3000/subscribe`
})
const user = await client.loginAnonymously('Jack');
const filePath = 'https://pdftron.s3.amazonaws.com/downloads/pl/webviewer-demo.pdf';
const createDocument = async () => {
const document = await user.createDocument({
document: filePath,
isPublic: true,
name: 'document.pdf'
});
await document.view(filePath);
}
document.getElementById('my-button').onclick = createDocument;
const publicDocPaginator = user.getPublicDocumentPaginator({ limit: 1 });
const publicDocuments = await publicDocPaginator.next();
publicDocuments.forEach(async document => {
if(await document.canJoin()) {
await document.join()
}
})
const documents = await user.getAllDocuments();
if(documents.length > 0) {
const mostRecentDocument = documents[0];
await mostRecentDocument.view(filePath);
}
});

The code we added uses the paginator class, which is used to fetch documents in an efficient way. You can read more about paginators here.

All this code is doing is fetching the latest public document, and joining it if we are able to. We could load and join more documents by increasing the limit parameter.

info

In a more complete app, you would typically render these public documents to your UI and allow the user to click a button to join the document.

Now, when the user loads the page, they will automatically join the last public document!

Collaborating#

The last step of this guide is actually collaborating on a document!

Opening the app in your browser will create a new anonymous user. That user can then click the my-button button to create a new public document. If you refresh the page, that new document will be automatically loaded!

In order to collaborate, we must have at least two users signed in. To accomplish this with our current set-up, we can open a new incognito window and go to our app. This will create a new anonymous user, and will also automatically join the document the first user created!

At this point you are able to draw annotations and see them sync in real time between users.

Next steps#

Now that you have all the modules implemented, we recommend learning more about the collaboration client.