npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pdfkarim

v0.1.1

Published

Pixel-Perfect React/Next.js to A4 PDF Generator

Readme

PdfKarim

Pixel-Perfect React/Next.js to A4 PDF Generator

📋 Overview

PdfKarim is an open-source NPM package that enables developers to export React.js and Next.js components as pixel-perfect, searchable, multi-page A4 PDFs with repeatable headers/footers and full i18n support.

Key Benefits

  • Exact CSS/HTML fidelity via headless-Chrome (Puppeteer)
  • Selectable, searchable text (no raster images)
  • Multi-page documents with consistent headers/footers
  • Supports any language, including RTL and CJK

✨ Features

Core Features

  • A4 page sizing & configurable margins (@page)
  • Multi-page support: honors CSS page-break-*
  • Repeatable header/footer: React components injected per page
  • Searchable text: HTML text preserved
  • Internationalization: UTF-8, RTL support
  • JS & TS: delivers .js, .d.ts
  • Hidden rendering via visible prop
  • Pluggable storage: Blob, Buffer, or custom handlers (S3, email)

Non-Functional Features

  • Performance: concurrent renders, asset caching
  • Bundle size: core < 100 KB (Puppeteer separate)
  • Compatibility: Node ≥14, React ≥16, Next.js ≥10
  • Security: input sanitization, render timeouts
  • Testing: 90%+ coverage (Jest)
  • Docs & examples: Storybook, CodeSandbox

🚀 Installation

npm install pdfkarim puppeteer --save
# or
yarn add pdfkarim puppeteer

🔧 Setup

Next.js API Route

Create an API route at pages/api/pdfkarim/render.js:

import { renderPdf } from 'pdfkarim/server';

export default async (req, res) => {
  const { html, options } = req.body;
  try {
    const buffer = await renderPdf(html, options);
    res.setHeader('Content-Type', 'application/pdf');
    res.send(buffer);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
};

// Increase the limit of the request body for large HTML content
export const config = {
  api: {
    bodyParser: {
      sizeLimit: '10mb',
    },
  },
};

📖 Usage

import { useRef } from 'react';
import { PdfKarim } from 'pdfkarim';

export default function MyComponent() {
  const pdfRef = useRef();
  
  const handleGeneratePdf = async () => {
    // Generate and download PDF
    await pdfRef.current.save('document.pdf');
  };
  
  return (
    <div>
      <button onClick={handleGeneratePdf}>Generate PDF</button>
      
      <PdfKarim
        ref={pdfRef}
        visible={false}
        header={<MyHeader />}
        footer={<MyFooter />}
        margins={{ top: 15, right: 15, bottom: 15, left: 15 }}
      >
        <MyContent />
      </PdfKarim>
    </div>
  );
}

📚 API Reference

<PdfKarim> Component

interface PdfKarimProps {
  visible?: boolean;  // default: false
  pageSize?: 'A4' | { width: number; height: number };  // mm
  margins?: { top: number; right: number; bottom: number; left: number };  // mm
  header?: ReactNode;  // rendered on each page
  footer?: ReactNode;  // rendered on each page
  timeoutMs?: number;  // render timeout
  onComplete?: (info: { totalPages: number }) => void;
  children: ReactNode;
}

interface PdfKarimHandle {
  save(fileName?: string): Promise<Blob>;
  getBlob(): Promise<Blob>;
  getBuffer(): Promise<Buffer>;
}

Props

  • visible: Controls visibility of the component (defaults to false, which renders off-screen)
  • pageSize: Either 'A4' or custom dimensions in mm
  • margins: Page margins in mm
  • header: Component to render as header on each page
  • footer: Component to render as footer on each page
  • timeoutMs: PDF generation timeout in milliseconds
  • onComplete: Callback fired when PDF generation completes
  • children: Content to render in the PDF

Methods

  • save(fileName): Generates PDF and triggers download
  • getBlob(): Returns PDF as a Blob
  • getBuffer(): Returns PDF as a Buffer (Node.js only)

🛠️ Architecture

PdfKarim uses a client-server architecture:

  1. The client-side React component captures and serializes DOM content
  2. The server-side Puppeteer service renders the HTML to a PDF
  3. The generated PDF is returned to the client

📖 Documentation

For more detailed information, see the following documentation:

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT