How to add a watermark with Next.js
Table of contents
This tutorial shows how to add custom watermarks to PDF pages in a Next.js application using Nutrient Web SDK’s renderPageCallback API. You’ll draw text and graphics on each page using the HTML5 Canvas API.
Prerequisites
Before starting, ensure you have:
- Node.js 18+ installed
- Basic knowledge of React and Next.js
- Familiarity with Nutrient Web SDK or the previous Next.js integration tutorial
Next.js(opens in a new tab) has become a popular React framework since its initial release(opens in a new tab). This tutorial demonstrates how to render custom watermarks on each page using the renderPageCallback configuration option.
What you’ll build
This example builds on Nutrient’s Next.js example(opens in a new tab), which is publicly available on GitHub.
The goal is to render a custom watermark on each page that appears 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.
Run npm run dev in the shell console for 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:
'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('@nutrient-sdk/viewer').then((NutrientViewer) => { if (NutrientViewer) { NutrientViewer.unload(container); }
NutrientViewer.load({ container, document: '/document.pdf', baseUrl: `${window.location.protocol}//${window.location.host}/`, }); }); } }, []);
return <div ref={containerRef} style={{ height: '100vh' }} />;}For more details, see the original blog post. Now you’ll add watermarking.
Nutrient Web SDK renders individual watermarks for each page through a callback function that receives a canvas context for drawing custom content.
This example adds the text “This is page x” to each page using NutrientViewer.Instance#renderPageCallback(). Here’s the callback function’s signature:
type RenderPageCallback(ctx: [CanvasRenderingContext2D][], pageIndex: number, size: [NutrientViewer.Size][])This callback is provided through the configuration object passed to NutrientViewer#load(). The drawing context already contains the page’s rendered content.
Draw on top of this context using the dimensions specified in the size argument:
NutrientViewer.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); },});Integrate the watermarking callback into the original example code in app/page.js:
'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('@nutrient-sdk/viewer').then((NutrientViewer) => { if (NutrientViewer) { NutrientViewer.unload(container); }
NutrientViewer.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' }} />;}With npm run dev running, the view updates in real time with a watermark (in Comic Sans) on each page.
Conclusion
As shown in the previous blog post, you can integrate PDF viewing and annotation into Next.js applications with Nutrient Web SDK.
Check out our demo to see Nutrient Web SDK in action, or start building your own Next.js PDF application.