Blog Post

How to Add a Watermark with Next.js

Illustration: How to Add a Watermark with Next.js

Next.js was initially released four years ago, and it has been steadily growing in popularity ever since. Last year, we wrote a tutorial, where we covered the details of integrating the Next.js JavaScript framework into PSPDFKit for Web.

Next.js has grown even more since that post, and it’s been improving with each new version. As a result, we wanted to take another look at it — this time, with an integration example that goes beyond opening and viewing a PDF document. Instead, we’ll showcase a more elaborate example that also highlights how easy it is to build web applications based on React.

The Goal

We’ll start off where the last post finished. That is, we’ll base our example off PSPDFKit’s Next.js example, which is publicly available on GitHub.

But in this post, we’ll implement an additional feature in our PDF viewer: We’ll render a custom watermark on each page that will appear on top of the content but below any annotations.

Setup

To get started, clone the repo, follow the installation instructions found in the repo’s readme.md, and open app/page.js in your favorite editor.

Feel free to run npm run dev in the shell console to enjoy hot reloading while applying changes to the code.

The Code

The original Next.js example consists of a component that loads and renders a PDF document. Let’s take a quick look at it:

'use client';
import { useEffect, useRef } from 'react';

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

	useEffect(() => {
		const container = containerRef.current;

		if (typeof window !== 'undefined') {
			import('pspdfkit').then((PSPDFKit) => {
				if (PSPDFKit) {
					PSPDFKit.unload(container);
				}

				PSPDFKit.load({
					container,
					document: '/document.pdf',
					baseUrl: `${window.location.protocol}//${window.location.host}/`,
				});
			});
		}
	}, []);

	return <div ref={containerRef} style={{ height: '100vh' }} />;
}

Simple enough. You can see the details in the original blog post if you want to see more. Now let’s add some watermark powers!

PSPDFKit for Web allows us to render individual watermarks for each page. But to do so, we have to provide a callback function to which the library will pass a canvas context where we can draw any content we want.

For this example, we’ll add the text “This is page x” to each page with the current page number, and we’ll do this using PSPDFKit.Instance#renderPageCallback(). Let’s have a look at the callback function’s signature:

type RenderPageCallback(ctx: [CanvasRenderingContext2D][], pageIndex: number, size: [PSPDFKit.Size][])

This callback must be provided through the configuration object passed to PSPDFKit#load(). The drawing context it receives already contains the page’s rendered content.

We’ll draw on top of this drawing context, which is limited only by the drawing context dimensions, which are specified in the provided size argument:

PSPDFKit.load({
	renderPageCallback: function (ctx, pageIndex, pageSize) {
		ctx.beginPath();
		ctx.fillStyle = 'red';
		ctx.fillRect(0, 0, pageSize.width, 40);
		ctx.stroke();
		ctx.font = '30px Comic Sans MS';
		ctx.fillStyle = 'white';
		ctx.textAlign = 'right';
		ctx.fillText(`This is page ${pageIndex + 1}`, pageSize.width, 30);
	},
});

Now we’re ready to integrate the watermarking callback to the original example code in app/page.js, which will now look like this:

'use client';
import { useEffect, useRef } from 'react';

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

	useEffect(() => {
		const container = containerRef.current;

		if (typeof window !== 'undefined') {
			import('pspdfkit').then((PSPDFKit) => {
				if (PSPDFKit) {
					PSPDFKit.unload(container);
				}

				PSPDFKit.load({
					container,
					document: '/document.pdf',
					baseUrl: `${window.location.protocol}//${window.location.host}/`,
					renderPageCallback: function (ctx, pageIndex, pageSize) {
						ctx.beginPath();
						ctx.fillStyle = 'red';
						ctx.fillRect(0, 0, pageSize.width, 40);
						ctx.stroke();
						ctx.font = '30px Comic Sans MS';
						ctx.fillStyle = 'white';
						ctx.textAlign = 'right';
						ctx.fillText(
							`This is page ${pageIndex + 1}`,
							pageSize.width,
							30,
						);
					},
				});
			});
		}
	}, []);

	return <div ref={containerRef} style={{ height: '100vh' }} />;
}
Information

Interact with the sandbox by clicking the left rectangle icon and selecting Editor > Show Default Layout. To edit, sign in with GitHub — click the rectangle icon again and choose Sign in. To preview the result, click the rectangle icon once more and choose Editor > Embed Preview. For the full example, click the Open Editor button. Enjoy experimenting with the project!

And that’s all it takes! If we’re already running npm run dev, we’ll see the view updating in real time, but now with a nice, good-looking (in Comic Sans!) watermark on each page.

Conclusion

As we saw in the previous blog post, building a Next.js application with PDF viewing and annotating capabilities can’t get much easier using PSPDFKit for Web. That’s because our Web SDK is an enterprise-ready PDF solution for web browsers and other platforms, and it features industry-leading first-class support.

That said, our SDK offers many possibilities beyond viewing PDFs. Check out our demo to see PSPDFKit for Web in action. I hope this post encourages you to try and build your own Next.js app with PDF superpowers!

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

Related Articles

Explore more
PRODUCTS  |  Web • Releases • Components

PSPDFKit for Web 2024.3 Features New Stamps and Signing UI, Export to Office Formats, and More

PRODUCTS  |  Web • Releases • Components

PSPDFKit for Web 2024.2 Features New Unified UI Icons, Shadow DOM, and Tab Ordering

PRODUCTS  |  Web

Now Available for Public Preview: New Document Authoring Experience Provides Glimpse into the Future of Editing