Blog post

How to build a Next.js PDF viewer

In this tutorial, you’ll integrate Nutrient Web SDK into a new Next.js project to display a PDF file.

Illustration: How to build a Next.js PDF viewer

Next.js is a powerful React framework optimized for building modern web applications. Nutrient Web SDK enables in-browser PDF and image viewing, annotation, redaction, and signing with a fast, WebAssembly-based rendering engine.

What is a Next.js PDF viewer?

A Next.js PDF viewer lets you render and view PDF documents in a web browser without the need to download it to your hard drive or use an external application like a PDF reader.

Nutrient Next.js PDF viewer

We offer a commercial Next.js PDF viewer library that can easily be integrated into your web application.

  • A prebuilt and polished UI for an improved user experience
  • 15+ prebuilt annotation tools to enable document collaboration
  • Support for more file types with client-side PDF, MS Office, and image viewing
  • Dedicated support from engineers to speed up integration

Example of our Next.js PDF viewer

To demo our Next.js PDF viewer, upload a PDF, JPG, PNG, or TIFF file by clicking Open Document under the Standalone option (if you don’t see this option, select Choose Example from the dropdown). Once your document is displayed in the viewer, try drawing freehand, adding a note, or applying a crop or an eSignature.

Requirements to get started

To get started, you’ll need:

Step 1 — Set up your Next.js project

Start by creating a fresh Next.js app:

npx create-next-app@latest nutrient-pdf-viewer
cd nutrient-pdf-viewer

Use the default settings when prompted.

Step 2 — Install the Nutrient SDK

Install the viewer package using npm:

npm install @nutrient-sdk/viewer

This command installs the SDK locally, enabling access to the viewer distribution files.

Step 3 — Copy the SDK assets

To run Nutrient in the browser, you need to expose the SDK assets publicly. Copy the required files into your project’s public directory:

cp -R ./node_modules/@nutrient-sdk/viewer/dist/ public/nutrient-viewer

You should see a new folder structure like this:

/public
  /nutrient-viewer
    nutrient-viewer.js
    nutrient-viewer-lib/

To automate this in development and production builds, modify package.json:

"scripts": {
  "copy-assets": "cp -R ./node_modules/@nutrient-sdk/viewer/dist/ public/nutrient-viewer",
  "dev": "npm run copy-assets && next dev",
  "build": "npm run copy-assets && next build"
}

Add public/nutrient-viewer/ to your .gitignore file to avoid committing binaries.

Step 4 — Add a PDF file

Place a sample file like document.pdf in your public directory. You can use our demo document as an example:

/public
  document.pdf

Step 5 — Load the PDF viewer

Before you write code, here’s how it works:

  1. Global script injection — Nutrient uses global variables, so you need to load the SDK script before any UI renders.

  2. Client-side rendering — The viewer must be initialized in a React component with useEffect so that it only loads in the browser.

  3. Cleanup — The viewer should be properly unloaded to avoid memory leaks.

The following section provides a step-by-step implementation.

1. Register the viewer script in the layout

Edit app/layout.tsx:

import Script from 'next/script';

export default function RootLayout({ children }) {
	return (
		<html lang="en">
			<head>
				<Script
					src="/nutrient-viewer/nutrient-viewer.js"
					strategy="beforeInteractive"
				/>
			</head>
			<body>{children}</body>
		</html>
	);
}

This ensures the SDK is loaded before your page component executes.

2. Add the PDF viewer component

In app/page.tsx or app/page.js, render the viewer dynamically on the client:

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

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

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

		if (container && NutrientViewer) {
			NutrientViewer.load({
				container,
				document: '/document.pdf',
			});
		}

		return () => {
			NutrientViewer?.unload(container);
		};
	}, []);

	return (
		<div
			ref={containerRef}
			style={{ width: '100%', height: '100vh' }}
		/>
	);
}

Make sure document.pdf exists and matches the file path exactly.

3. Configure webpack to exclude bundling

In next.config.js, prevent webpack from bundling the SDK into your app:

const nextConfig = {
	webpack: (config, { isServer }) => {
		if (!isServer) {
			config.externals = config.externals || [];
			config.externals.push({
				'@nutrient-sdk/viewer': '@nutrient-sdk/viewer',
			});
		}
		return config;
	},
	experimental: {
		turbo: {
			resolveAlias: {
				'@nutrient-sdk/viewer': '@nutrient-sdk/viewer',
			},
		},
	},
};

export default nextConfig;

Step 6 — Start the development server

Run your project:

npm run dev

Navigate to http://localhost:3000/ in your browser. You’ll see all the features you expect from a PDF viewer are present by default.

nutrient demo

Adding even more capabilities

Once you’ve deployed 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 Next.js guides:

Conclusion

With Nutrient Web SDK and Next.js, you can deliver a seamless PDF viewing experience directly in your app — with full control over rendering, styling, and interaction.

You can also deploy our vanilla JavaScript PDF viewer or use one of our many web framework deployment options like React.js, Vue.js, jQuery, and Angular.

To see a list of all web frameworks, start your free trial. Or, launch our demo to see our viewer in action.

FAQ

What is Nutrient Web SDK? Nutrient Web SDK is a browser-based JavaScript library that allows you to render, annotate, redact, and sign PDF and image files using WebAssembly for high performance and full client-side operation.
Can I use Nutrient Web SDK with PDF files only? No. While it excels at PDF rendering, it also supports Office formats (like DOCX and XLSX) and image formats (JPG, PNG, TIFF), making it versatile for most document-centric applications.
Is the SDK suitable for production apps? Yes. Nutrient Web SDK is an enterprise-grade commercial library designed for production use. It includes advanced features, robust rendering, dedicated support, and flexible deployment options.
How do I avoid bundling the SDK in my Next.js app? To keep the SDK out of your webpack bundle, load it via a global script tag and mark it as external in your Next.js next.config.js file. This keeps your build lean and avoids redundant packaging.
Do I need a backend server to use the PDF viewer? No. The viewer runs fully in the browser. As long as your PDF file is publicly accessible (e.g. in the /public directory), you can load and interact with it without any backend processing.
Author
Hulya Masharipov
Hulya Masharipov Technical Writer

Hulya is a frontend web developer and technical writer at Nutrient who enjoys creating responsive, scalable, and maintainable web experiences. She’s passionate about open source, web accessibility, cybersecurity privacy, and blockchain.

Explore related topics

Free trial Ready to get started?
Free trial