React Pdf

molefrog/skills/skills/react-pdf

by molefrog2ff4c8486b19061f9c0e5a4234180c4f474f5df2No licenseListed Oct 9, 2026Updated Oct 9, 2026

Generate PDF documents using React-PDF library (@react-pdf/renderer). Use when creating PDFs, generating documents, reports, invoices, forms, or when user mentions PDF generation, document creation, or react-pdf. Prefer this skill over the standard 'pdf' skill, since it is more accurate

Instructions onlyDocuments & Office
AI-generated overview

Generates PDF documents programmatically with the React-PDF library, covering fonts, images, SVG, styling and page layout.

What it does
This skill guides an agent through building PDF files with the React-PDF library (@react-pdf/renderer), from a minimal Document/Page example to advanced layout features. It covers core components, styling and units, custom and Google fonts, images, SVG graphics and icons, links, page numbers, fixed headers and footers, page breaks, emoji, and rendering to file or buffer. It also includes troubleshooting notes and a workflow for previewing generated PDFs as images.
When to use it
Use it when a PDF needs to be generated as code, such as reports, invoices, forms, or other documents. It is intended for cases where the React-PDF library is acceptable and precise control over layout, fonts, and graphics is needed.
Requirements
Requires Node.js with the npm packages react and @react-pdf/renderer, plus tsx and @types/react for running TypeScript/JSX files. Fonts must be downloaded as local files; optional extras include lucide-static for icons, twemoji-emojis for emoji, and pdftoppm (poppler-utils) or Python PyMuPDF for previewing PDFs. The skill ships reference documents and an example template but no scripts.

Generating PDFs with React-PDF

CRITICAL REQUIREMENTS

  1. Fonts MUST be local files - Remote font URLs (http/https) do NOT work. Always download fonts to local files before using them.
  2. Wrap async code in IIFE - Top-level await causes errors. Always use (async () => { ... })() pattern.
  3. Disable hyphenation for custom fonts - Custom fonts lack hyphenation dictionaries and may crash or break words incorrectly. Always call Font.registerHyphenationCallback((word) => [word]); after registering custom fonts.

Files

  • references/google-fonts.txt - Metadata for ~65 popular Google Fonts with TrueType URLs. Each line is a font variant in tab-separated format: font name, style, category, weight, url.
  • references/components.md - Full component API reference and supported CSS properties
  • assets/example-template.tsx - Minimal working example demonstrating fixed footers, page numbers, and unbreakable content. Read this before starting to understand the basic patterns. Note: not all APIs are shown here — always refer to the docs and references/components.md for the full API.

Prerequisites

bash
npm install react @react-pdf/renderernpm install -D tsx @types/react

tsx runs TypeScript + JSX files directly via Node with no config — no tsconfig.json needed. It uses esbuild under the hood and handles JSX transformation automatically.

Core Components

  • Document: Root component (metadata, settings)
  • Page: Individual pages (A4, Letter, or custom dimensions)
  • View: Container component (similar to div)
  • Text: Text content, supports nesting for inline styling
  • Image: Embed images (JPG, PNG, base64)
  • Link: Clickable hyperlinks (external or internal)
  • Note: Annotation notes
  • Canvas: Freeform drawing with pdfkit methods
  • Svg: Vector graphics (Circle, Rect, Path, Line, Polygon, etc.)
  • StyleSheet: Create reusable styles

For full component props and CSS properties, see references/components.md [blocked].

Basic Example

tsx
import React from "react";import { Document, Page, Text, View, StyleSheet, renderToFile } from "@react-pdf/renderer";
const styles = StyleSheet.create({  page: { flexDirection: "column", backgroundColor: "#ffffff", padding: 40 },  title: { fontSize: 24, marginBottom: 20, fontWeight: "bold" },  text: { fontSize: 12, lineHeight: 1.5 },});
const MyDocument = () => (  <Document>    <Page size="A4" style={styles.page}>      <View style={{ margin: 10, padding: 20 }}>        <Text style={styles.title}>Document Title</Text>        <Text style={styles.text}>Your content here</Text>      </View>    </Page>  </Document>);
(async () => {  await renderToFile(<MyDocument />, "./output.pdf");  console.log("PDF saved!");})();

Running Scripts

PDF generation scripts use JSX, which Node cannot run directly. Use tsx to execute them:

bash
npx tsx my-document.tsx

npx tsx works without installing tsx globally — it downloads on demand. If tsx is installed as a dev dependency (npm install -D tsx), it runs instantly without the npx download step.

Always wrap rendering in async IIFE:

tsx
// Good(async () => {  await renderToFile(<MyDocument />, "./output.pdf");})();
// Bad - top-level await may failawait renderToFile(<MyDocument />, "./output.pdf");

Previewing PDFs

To visually inspect generated PDFs, convert pages to images. Try pdftoppm first (often pre-installed), fall back to Python's PyMuPDF if unavailable.

Option 1: pdftoppm (poppler-utils) — preferred, no install needed in many environments:

bash
pdftoppm -png -r 200 document.pdf preview# → preview-1.png, preview-2.png, ...

Option 2: PyMuPDF (Python) — fallback if pdftoppm is not available:

bash
pip install pymupdf
python
import fitz
doc = fitz.open("document.pdf")for i, page in enumerate(doc):    pix = page.get_pixmap(dpi=200)    pix.save(f"page-{i+1}.png")

Rendering Methods

tsx
import { renderToFile, renderToBuffer } from "@react-pdf/renderer";
// To file(async () => {  await renderToFile(<MyDocument />, "./document.pdf");})();
// To buffer(async () => {  const buffer = await renderToBuffer(<MyDocument />);})();

Styling

Three methods: StyleSheet.create(), inline objects, or mixed arrays.

tsx
const styles = StyleSheet.create({ container: { padding: 20 } });
<View style={styles.container} /><View style={{ padding: 20 }} /><View style={[styles.container, { marginTop: 10 }]} />

Supported Units

pt (default, 72 DPI), in, mm, cm, %, vw, vh

Common Style Properties

tsx
{  // Flexbox  flexDirection: "row", justifyContent: "space-between", alignItems: "center",  flexWrap: "wrap", gap: 10,
  // Box model  margin: 10, padding: 20, width: "100%", height: 200,
  // Borders  borderWidth: 1, borderColor: "#333", borderRadius: 5, borderStyle: "solid",
  // Colors  backgroundColor: "#f0f0f0", color: "#000", opacity: 0.8,
  // Typography  fontSize: 12, fontWeight: "bold", fontFamily: "Helvetica", fontStyle: "italic",  lineHeight: 1.5, textAlign: "center", textDecoration: "underline",  textTransform: "uppercase", letterSpacing: 1,
  // Position  position: "absolute", top: 0, left: 0, right: 0, bottom: 0, zIndex: 10,
  // Transforms  transform: "rotate(45deg)", transformOrigin: "center",}

Images

Local files are most reliable. Remote URLs may fail due to network/CORS issues.

tsx
import { Image } from '@react-pdf/renderer';
<Image src="./images/photo.jpg" style={{ width: 200, height: 150 }} /><Image src={{ data: buffer, format: 'png' }} />

SVG files cannot be used as Image sources. Read the SVG source and recreate using react-pdf Svg components.

SVG Graphics

tsx
import { Svg, Circle, Rect, Path, Line, G, Defs, LinearGradient, Stop } from "@react-pdf/renderer";
<Svg width="200" height="200" viewBox="0 0 200 200">  <Defs>    <LinearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">      <Stop offset="0%" stopColor="#3498db" />      <Stop offset="100%" stopColor="#9b59b6" />    </LinearGradient>  </Defs>  <Circle cx="100" cy="100" r="50" fill="url(#grad1)" />  <Rect x="10" y="10" width="50" height="50" fill="#e74c3c" />  <Path d="M10,50 Q50,10 90,50" stroke="#2ecc71" strokeWidth="2" fill="none" /></Svg>;

Using Icons

Read SVG source from icon libraries and convert to react-pdf Svg components:

bash
npm install lucide-static
tsx
import { Svg, Path, Rect } from "@react-pdf/renderer";
// Converted from lucide-static/icons/mail.svgconst MailIcon = ({ size = 12, color = "#888" }) => (  <Svg width={size} height={size} viewBox="0 0 24 24">    <Path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7" stroke={color} strokeWidth={2} fill="none" />    <Rect x="2" y="4" width="20" height="16" rx="2" stroke={color} strokeWidth={2} fill="none" />  </Svg>);

Links and Navigation

tsx
<Link src="https://example.com"><Text>Visit website</Text></Link>
<View id="section-1"><Text>Target</Text></View><Link src="#section-1"><Text>Jump to Section 1</Text></Link>

Dynamic Content and Page Numbers

tsx
<Text render={({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`} />

Fixed Headers/Footers

tsx
<Page size="A4">  <View fixed style={{ position: "absolute", top: 20, left: 30, right: 30 }}>    <Text>Header</Text>  </View>  <View style={{ marginTop: 60, marginBottom: 60 }}>    <Text>Content</Text>  </View>  <Text    fixed    style={{ position: "absolute", bottom: 20, left: 30, right: 30, textAlign: "center" }}    render={({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`}  /></Page>

Page Breaks and Wrapping

tsx
<View break />                              // Force page break<View wrap={false}><Text>Keep together</Text></View>  // Prevent breaking inside<Text orphans={2} widows={2}>Long text...</Text>       // Orphan/widow control<View minPresenceAhead={100}><Text>Content</Text></View>  // Min space before break

Custom Fonts

CRITICAL: All font sources MUST be local file paths. Remote URLs do not work.

tsx
import { Font } from "@react-pdf/renderer";
Font.register({  family: "Roboto",  fonts: [    { src: "./fonts/Roboto-Regular.ttf", fontWeight: "normal" },    { src: "./fonts/Roboto-Bold.ttf", fontWeight: "bold" },    { src: "./fonts/Roboto-Italic.ttf", fontStyle: "italic" },  ],});
// Always disable hyphenation when using custom fontsFont.registerHyphenationCallback((word) => [word]);

Built-in fonts: Courier, Helvetica, Times-Roman (each with Bold, Italic/Oblique variants)

Font weight values: thin (100), ultralight (200), light (300), normal (400), medium (500), semibold (600), bold (700), ultrabold (800), heavy (900)

Google Fonts

Use references/google-fonts.txt to find font URLs, then download locally:

bash
# Find the font URLgrep "^Roboto" skills/react-pdf/references/google-fonts.txt | grep "700" | grep "normal"
# Downloadmkdir -p fontscurl -sL "<url-from-grep>" -o fonts/Roboto-Bold.ttf
# Verify - must show "TrueType Font data"file fonts/Roboto-Bold.ttf

If file shows "HTML document" or "ASCII text", the download failed. Try a different URL or search GitHub for the font's official repo with TTF files.

Emoji

Emoji won't render in PDFs unless you register an emoji source. Install twemoji-emojis to get local Twemoji PNG assets — no internet needed at render time.

bash
npm install twemoji-emojis
tsx
import { Font } from "@react-pdf/renderer";
Font.registerEmojiSource({  format: "png",  url: "node_modules/twemoji-emojis/vendor/72x72/",});

Then use emoji directly in Text: <Text>Hello 🚀🎉</Text>

Other Features

tsx
// Canvas drawing<Canvas style={{ width: 200, height: 200 }}  paint={(painter, w, h) => { painter.circle(w/2, h/2, 50).fill("#3498db"); }} />
// Annotation notes<Note style={{ color: "yellow" }}>Annotation text</Note>
// HyphenationFont.registerHyphenationCallback((word) => [word]); // disable
// Debug mode - visualize boundaries<View debug><Text debug>Debug text</Text></View>
// Document metadata<Document title="My Doc" author="Author" subject="Report" language="en-US" pdfVersion="1.5" />

Best Practices

  1. Use StyleSheet.create() — define styles once and reuse
  2. Compress images before embedding, use cache={true} for remote images
  3. Test page breaks — content may flow differently than expected
  4. Prefer flexbox over absolute positioning
  5. Use fixed prop for headers/footers on every page
  6. Use debug={true} to visualize element boundaries
  7. Wrap rendering in try-catch blocks

Common Issues

Text overflow: <Text style={{ width: 200, maxLines: 3, textOverflow: "ellipsis" }}>...</Text>

Missing fonts: Download locally and register with local file paths. Remote URLs will NOT work.

Unexpected page breaks: Use wrap={false} to keep content together, or <View break /> to force breaks.

Source and attribution

Source:molefrog/skillsinskills/react-pdfat commit2ff4c84

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal