We are your Digital Ally™
PDF Without Worries
tech

PDF Without Worries

Comparing two approaches to programmatic PDF generation in Node.js: react-pdf for React-native document composition, and Puppeteer for full-browser HTML-to-PDF conversion.

Instea TeamMarch 1, 2021

Generating PDFs programmatically is a common requirement — reports, invoices, exports. But picking the right tool matters. Here is what we looked for:

  • Styling (fonts, colors, etc.)
  • Tables with a repeating header on every page
  • Header/footer on every page with page numbers
  • Running custom code (for charts, maps, etc.)

We evaluated two approaches: react-pdf and Puppeteer.

React-pdf

React-pdf combines React for layout definition with PDFKit for rendering. It supports both client-side and server-side rendering without relying on HTML-to-PDF conversion.

Key features:

  • CSS and flexbox-based styling
  • Simple component-based approach familiar to React developers
  • Metadata support and live preview capability

Server-side rendering example:

const { default: ReactPDF } = require("@react-pdf/renderer");
ReactPDF.render(<OneLinePDF />, `react-pdf.pdf`);

Tables in react-pdf

React-pdf has no native table component. Tables are built by styling View and Text elements with flexbox. A basic table looks like this:

react-pdf table example — row breaking problem

A critical issue: table rows can break across pages. The fix is to add wrap={false} to rows you want to keep together:

react-pdf table with wrap=false fix

Repeating table headers are not supported natively and require manual row counting to replicate the header at page boundaries.

Header / Footer

Achieved via fixed View elements with absolute positioning. Page numbers are accessed through render functions that receive pageNumber as a parameter.

Custom Code Limitation

Canvas support exists, but integration with external charting or mapping libraries is impractical. Google Maps integration proved particularly problematic.

Live Preview

One unique advantage: react-pdf supports a live in-browser preview of the document as you edit.

react-pdf live preview


Puppeteer

Puppeteer controls a headless Chrome instance via Node.js, enabling HTML-to-PDF conversion with the full power of a real browser.

Basic implementation:

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setContent(html);
await page.pdf({ path: "puppeteer.pdf" });
await browser.close();

Tables in Puppeteer

Native HTML <table> support means table headers (<thead>) repeat automatically across pages. Cell breaking is prevented automatically.

Puppeteer table output

Puppeteer table — final result

Header / Footer

Template-based approach using headerTemplate and footerTemplate parameters with inline CSS. Page numbers are injected via special class-based placeholders (pageNumber, totalPages).

Puppeteer header/footer example

Custom Code

Full JavaScript engine access enables charting libraries, Google Maps rendering, and any other dynamic content — a significant advantage over react-pdf.

Limitations

  • No document metadata support
  • No document encryption or editable form creation
  • Resource-intensive (spawns a full Chrome process)
  • Can be tricky to deploy on serverless platforms like AWS Lambda

Conclusion

Neither solution is universally better — it depends on your project's requirements:

react-pdfPuppeteer
Client-side renderingYesNo
Metadata supportYesNo
Native HTML tablesNoYes
Repeating table headersManual workaroundAutomatic
Custom code (charts, maps)LimitedFull
Cloud deploymentEasyChallenging

react-pdf excels for simple, self-contained documents where React integration matters. Puppeteer wins for flexibility, especially when your requirements are still evolving — its HTML foundation means you can swap rendering strategies without rewriting templates.

© 2026