Blog Post

How to Build a PDF Viewer with Remix and PSPDFKit

Igor Perzić
Illustration: How to Build a PDF Viewer with Remix and PSPDFKit

This post will provide you with a comprehensive look at how you can build a Remix PDF viewer from new or existing Remix apps and our Web PDF SDK. Using our PDF SDK will allow your users to open and annotate PDF documents with ease and speed.

Remix is an up-and-coming full stack web framework for React that’s made by the creators of React Router (and it uses React Router underneath too). It allows for server rendering, data loading, and routing, and it’s often compared to Next.js.

Creating the Remix PDF Viewer

This section will walk you through creating your Remix PDF viewer.

Prerequisites

First, you need to install:

  • Node.js version 14 or higher.

  • npm version 7 or greater.

ℹ Info: When you install Node.js, npm is installed by default.

Creating a New Remix Project

If you’re integrating PSPDFKit into an existing Remix app, feel free to skip to the next section.

To create a new Remix project, open a terminal of your choice and run:

npx create-remix@latest

During the project creation process, you’ll be presented with several options:

  1. Setting the project location and name

  2. A choice for the type of app you want to create

  3. Deployment target choice

  4. Language choice (TypeScript or JavaScript)

  5. Whether or not you want the tool to run npm install

We’ll cover these next.

ℹ️ Note: The first time you run the create-remix package, you’ll be asked if you want to install it. Type y (for yes) to proceed.

Start by setting the name and location of the project, i.e. pspdfkit-remix.

For the sake of simplicity, you’ll create a project with the basic options. So, when prompted for the type of Remix app you want to create, select the option for Just the basics. If you want to learn more about Remix app types, take a look at the Remix documentation.

Next, choose Remix App Server for the deployment target. This can be changed at a later stage.

In this tutorial, we chose JavaScript as our language and let Remix run npm install for us.

Your installation process will look something like this:

Remix project creation result

Adding PSPDFKit

If everything went fine, you’ll have successfully set up the Remix project and you can add PSPDFKit and start building the viewer. This consists of three steps, outlined below.

  1. Change your directory to the path specified when creating an app:

cd pspdfkit-remix
  1. Install pspdfkit as a dependency with npm:

npm install pspdfkit
  1. After installation, copy the PSPDFKit library assets to the assets folder, which, by default, is named public:

cp -R ./node_modules/pspdfkit/dist/pspdfkit-lib public/pspdfkit-lib

Or better yet, you can automate this so that it’s automagically done for you every time you install your packages. To do this, go to your package.json file and modify the postinstall script:

// package.json
...
 "scripts": {
    "build": "remix build",
    "dev": "remix dev",
-    "postinstall": "remix setup node",
+    "postinstall": "cp -R ./node_modules/pspdfkit/dist/pspdfkit-lib ./public/pspdfkit-lib && remix setup node",
    "start": "remix-serve build"
  }
...

Displaying the PDF

Now, for the fun part: displaying the PDF. Feel free to use our demo document for testing. Create an assets folder inside the public folder and place the desired PDF there.

Next, change the index page so that it displays your PDF viewer:

// app/routes/index.js

import { useEffect, useRef } from 'react';

export default function Index() {
	const containerRef = useRef(null);

	useEffect(() => {
		const container = containerRef.current;
		let instance, PSPDFKit;
		(async function () {
			PSPDFKit = (await import('pspdfkit')).default;
			instance = await PSPDFKit.load({
				container,
				document: 'assets/pspdfkit-web-demo.pdf',
				baseUrl: `${window.location.protocol}//${window.location.host}/`,
				licenseKey: 'YOUR_LICENSE_KEY_GOES_HERE',
			});
		})();

		return () => PSPDFKit && PSPDFKit.unload(container);
	}, []);

	return (
		<div>
			<div>
				Hello from Remix! Look at this pretty PDF we've got for you:
			</div>
			<div
				ref={containerRef}
				style={{ width: '100%', height: '100vh' }}
			/>
		</div>
	);
}

ℹ️ Note: The viewer container needs to have height explicitly set, otherwise you may get an error.

Now, take a closer look at the changes above. You created a containerRef reference to the element you’re going to mount PSPDFKit to, and then you lazily loaded the pspdfkit package inside the React useEffect hook. This enables you to load the document with the desired configuration.

For the most basic use case of displaying a PDF, there are only a few things you need to specify:

  • container — a CSS selector or the actual HTML element where you want to display the PDF (hence containerRef)

  • document — the relative path to the document you want to display, or an ArrayBuffer

  • licenseKey — your license key

  • baseUrl — the URL of your assets. By default, PSPDFKit assumes the assets folder is present in the same folder of your application module, but in this tutorial, you kept it inside the public folder, so you’ll have to pass a baseUrl option while initializing PSPDFKit.

You can read more about the available configuration options in our API docs.

Lastly, start the app to see the viewer. Run the command below and open http://localhost:3000 in your favorite web browser:

npm run dev

You’ve successfully added the PSPDFKit viewer to a Remix app!

Dynamically Loading PDFs

Simply displaying a static PDF doesn’t provide much flexibility. What if you want to load a PDF from an API or some other data source?

This is where Remix comes in handy with its loader functions. Go ahead and write a loader function that first makes an API call to fetch the PDF and then forwards it to the index page as a buffer:

import { useLoaderData } from 'remix';

export const loader = async () => {
	try {
		const response = await fetch(
			'https://web-examples.pspdfkit.com/hello/example.pdf',
		);

		return await response.buffer();
	} catch (e) {
		return { error: e.message };
	}
};

Now, take that buffer and display it using PSPDFKit. Remember reading above that the PSPDFKit SDK accepts an ArrayBuffer for a document? Well, this is exactly the type of situation where it’d come in handy. Now, your entire index page will look like this:

// app/routes/index.js

import { useEffect, useRef } from "react";
+ import { useLoaderData } from 'remix'

+ export const loader = async () => {
+     try {
+        const response = await fetch('https://web-examples.pspdfkit.com/hello/example.pdf')
+
+        return await response.buffer()
+    } catch (e) {
+        return { error: e.message }
+    }
};

export default function Index() {
    const containerRef = useRef(null);
+    const { data, error } = useLoaderData();

-    useEffect(() => {
+    useEffect(async () => {
+        if (!error) {
+            const document = new ArrayBuffer(data.length);
+            const view = new Uint8Array(document);
+
+	           for (let i = 0; i < data.length; ++i) {
+                view[i] = data[i];
+            }

            const container = containerRef.current;
            let instance, PSPDFKit;
            (async function () {
                PSPDFKit = (await import("pspdfkit")).default;
                instance = await PSPDFKit.load({
                    container,
-                    document: 'assets/pspdfkit-web-demo.pdf',
+                    document,
                    baseUrl: `${window.location.protocol}//${window.location.host}/`,
                    licenseKey: "YOUR_LICENSE_KEY_GOES_HERE",
                });
            })();

            return () => PSPDFKit && PSPDFKit.unload(container);
+        }
    }, []);

    return (
        <div>
            <div>Hello from Remix! Look at this pretty PDF we've got for you:</div>
            <div ref={containerRef} style={{ width: "100%", height: "100vh" }} />
        </div>
    );
}

And voilà, you’ve configured the viewer to load a PDF on the server by making an API call and then serving it as part of the page! 🎉

Adding Even More Capabilities

Once you’ve built your viewer, you can start customizing it to meet your specific requirements or easily add more capabilities. To help you get started, here are some of our most popular Remix guides:

Conclusion

You should now have our Remix PDF viewer up and running in your web application. If you hit any snags, don’t hesitate to reach out to our support team for help.

You can also deploy our vanilla JavaScript PDF viewer or use one of our many web framework deployment options like Vue.js, React.js, and jQuery. To see a list of all web frameworks, start your free trial. Or, launch our demo to see our viewer in action.

Related Products
Share Post
Free 60-Day Trial Try PSPDFKit in your app today.
Free Trial

Related Articles

Explore more
TUTORIALS  |  Web • JavaScript • How To • PDF Viewer

How to Build a JavaScript Image Viewer with Viewer.js

PRODUCTS  |  Web • Releases • Components

PSPDFKit for Web 2022.4 Renders Media Annotations

WEB  |  Web • Vue.js • JavaScript • How to • PDF Generation

Generate a PDF from HTML with Vue.js