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' }} />; }
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!