react-pdf-kit-nextjs-pages-router — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited react-pdf-kit-nextjs-pages-router (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this skill when: the developer asks to add a PDF viewer using @react-pdf-kit/viewer to a Next.js Pages Router project (pages/ directory) on Next.js 15+. For App Router use react-pdf-kit-nextjs-app-router. Next.js 14 is not supported by v2 — see react-pdf-kit-nextjs14-pdfjs-override.
The Pages Router runs every page through SSR by default. The viewer is client-only (it relies on browser APIs), so it must be mounted with next/dynamic and ssr: false.
during SSR with TypeError: Promise.withResolve is not a function (or a window is not defined style error). Always import the viewer via next/dynamic with ssr: false, and put 'use client' on the viewer component.
@react-pdf-kit/viewer. Do NOT install pdfjs-distseparately.** It is an auto-installed peer dependency. No worker configuration is required — RPConfig handles it. Version overrides and custom worker URLs live in react-pdf-kit-worker-config.
_app.tsxruns on the server too. Keep the viewer in its own dynamically-imported, ssr: false component.
RPLayout.pnpm add @react-pdf-kit/viewer// components/PdfViewer.tsx
'use client'
import {
RPConfig,
RPProvider,
RPLayout,
RPPages,
} from '@react-pdf-kit/viewer'
export default function PdfViewer({ src }: { src: string }) {
return (
<RPConfig>
<RPProvider src={src}>
<RPLayout toolbar>
<RPPages />
</RPLayout>
</RPProvider>
</RPConfig>
)
}Note the default export: next/dynamic works most ergonomically with default exports. RPConfig handles the worker and theming; licenseKey is an optional prop (without it, the viewer is in trial mode with a watermark).
next/dynamic with ssr: false// pages/document/[id].tsx
import dynamic from 'next/dynamic'
import { useRouter } from 'next/router'
const PdfViewer = dynamic(() => import('../../components/PdfViewer'), {
ssr: false,
loading: () => <div>Loading viewer...</div>,
})
export default function DocumentPage() {
const router = useRouter()
const id = router.query.id as string | undefined
return (
<main style={{ height: '100vh' }}>
{id ? <PdfViewer src={`/api/documents/${id}.pdf`} /> : null}
</main>
)
}The id guard avoids mounting the viewer with undefined on the first client render (before the router has hydrated).
pnpm install
pnpm build # must succeed under SSR + production build
pnpm dev # visit /document/<id>SSR should produce HTML containing the loading state, then the viewer mounts client-side after hydration. The first PDF page should render with the default toolbar, text selection should work, and there should be no Promise.withResolve is not a function error in the console.
next/dynamic API: <https://nextjs.org/docs/pages/api-reference/components/dynamic>react-pdf-kit-nextjs14-pdfjs-override: read this if the projectis on Next.js 14 (v2 is unsupported there).
react-pdf-kit-nextjs-app-router: for App Router projects.react-pdf-kit-worker-config: for pdfjs-dist version overridesand custom worker URLs.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.