react-pdf

Generates PDF documents using the React-PDF library (@react-pdf/renderer) with TypeScript and JSX. Use when creating PDFs, generating reports, invoices, forms, resumes, or any document that needs flexbox layout, SVG graphics, custom fonts, or professional typesetting. Prefer over Python PDF libraries (ReportLab, fpdf2) when layout complexity matters.

320 stars

Best use case

react-pdf is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Generates PDF documents using the React-PDF library (@react-pdf/renderer) with TypeScript and JSX. Use when creating PDFs, generating reports, invoices, forms, resumes, or any document that needs flexbox layout, SVG graphics, custom fonts, or professional typesetting. Prefer over Python PDF libraries (ReportLab, fpdf2) when layout complexity matters.

Teams using react-pdf should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/react-pdf/SKILL.md --create-dirs "https://raw.githubusercontent.com/trailofbits/skills-curated/main/plugins/react-pdf/skills/react-pdf/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/react-pdf/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How react-pdf Compares

Feature / Agentreact-pdfStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Generates PDF documents using the React-PDF library (@react-pdf/renderer) with TypeScript and JSX. Use when creating PDFs, generating reports, invoices, forms, resumes, or any document that needs flexbox layout, SVG graphics, custom fonts, or professional typesetting. Prefer over Python PDF libraries (ReportLab, fpdf2) when layout complexity matters.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Generating PDFs with React-PDF

## When to Use

- Generating PDF documents (reports, invoices, resumes, forms, certificates)
- Creating PDFs that need complex layouts (multi-column, grids, cards)
- Building PDFs with inline SVG graphics, charts, or icons
- Producing documents with custom Google Fonts or emoji
- Any PDF task where flexbox layout is easier than absolute coordinate math

## When NOT to Use

- Reading or extracting text from existing PDFs — use `pdfplumber` or `pypdf` instead
- Filling existing PDF forms — use Python `pypdf` or `pdftk`
- Converting HTML to PDF — use Playwright or WeasyPrint instead
- Simple one-off text PDFs with no layout needs — a Python script may be simpler

## 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

- `{baseDir}/skills/react-pdf/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`.
- `{baseDir}/skills/react-pdf/references/components.md` - Full component API reference and supported CSS properties
- `{baseDir}/skills/react-pdf/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 `{baseDir}/skills/react-pdf/references/components.md` for the full API.

## Prerequisites

```bash
npm install react @react-pdf/renderer
npm 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]({baseDir}/skills/react-pdf/references/components.md).

## 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 fail
await 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.svg
const 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 fonts
Font.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 `{baseDir}/skills/react-pdf/references/google-fonts.txt` to find font URLs, then download locally:

```bash
# Find the font URL
grep "^Roboto" {baseDir}/skills/react-pdf/references/google-fonts.txt | grep "700" | grep "normal"

# Download
mkdir -p fonts
curl -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>

// Hyphenation
Font.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.

Related Skills

x-research

320
from trailofbits/skills-curated

Searches X/Twitter for real-time perspectives, dev discussions, product feedback, breaking news, and expert opinions using the X API v2. Provides search with engagement sorting, user profiles, thread fetching, watchlists, and result caching. Use when: (1) user says "x research", "search x for", "search twitter for", "what are people saying about", "what's twitter saying", "check x for", "x search", (2) user needs recent X discourse on a topic (library releases, API changes, product launches, industry events), (3) user wants to find what devs/experts/community thinks about a topic. NOT for: posting tweets or account management.

wooyun-legacy

320
from trailofbits/skills-curated

Provides web vulnerability testing methodology distilled from 88,636 real-world cases from the WooYun vulnerability database (2010-2016). Use when performing penetration testing, security audits, code reviews for security flaws, or vulnerability research. Covers SQL injection, XSS, command execution, file upload, path traversal, unauthorized access, information disclosure, and business logic flaws.

skill-extractor

320
from trailofbits/skills-curated

Extracts reusable skills from work sessions. Use when: (1) a non-obvious problem was solved worth preserving, (2) a pattern was discovered that would help future sessions, (3) a workaround or debugging technique needs documentation. Manual invocation only via /skill-extractor command - no automatic triggers or hooks.

security-awareness

320
from trailofbits/skills-curated

Teaches agents to recognize and avoid security threats during normal activity. Covers phishing detection, credential protection, domain verification, and social engineering defense. Use when building or operating agents that access email, credential vaults, web browsers, or sensitive data.

scv-scan

320
from trailofbits/skills-curated

Audits Solidity codebases for smart contract vulnerabilities using a four-phase workflow (cheatsheet loading, codebase sweep, deep validation, reporting) covering 36 vulnerability classes. Use when auditing Solidity contracts for security issues, performing smart contract vulnerability scans, or reviewing Solidity code for common exploit patterns.

planning-with-files

320
from trailofbits/skills-curated

Implements file-based planning for complex multi-step tasks. Creates task_plan.md, findings.md, and progress.md as persistent working memory. Use when starting tasks requiring >5 tool calls, multi-phase projects, research, or any work where losing track of goals and progress would be costly.

openai-yeet

320
from trailofbits/skills-curated

Use only when the user explicitly asks to stage, commit, push, and open a GitHub pull request in one flow using the GitHub CLI (`gh`). Originally from OpenAI's curated skills catalog.

openai-spreadsheet

320
from trailofbits/skills-curated

Use when tasks involve creating, editing, analyzing, or formatting spreadsheets (`.xlsx`, `.csv`, `.tsv`) using Python (`openpyxl`, `pandas`), especially when formulas, references, and formatting need to be preserved and verified. Originally from OpenAI's curated skills catalog.

openai-sentry

320
from trailofbits/skills-curated

Use when the user asks to inspect Sentry issues or events, summarize recent production errors, or pull basic Sentry health data via the Sentry API; perform read-only queries with the bundled script and require `SENTRY_AUTH_TOKEN`. Originally from OpenAI's curated skills catalog.

openai-security-threat-model

320
from trailofbits/skills-curated

Repository-grounded threat modeling that enumerates trust boundaries, assets, attacker capabilities, abuse paths, and mitigations, and writes a concise Markdown threat model. Trigger only when the user explicitly asks to threat model a codebase or path, enumerate threats/abuse paths, or perform AppSec threat modeling. Do not trigger for general architecture summaries, code review, or non-security design work. Originally from OpenAI's curated skills catalog.

openai-security-ownership-map

320
from trailofbits/skills-curated

Analyze git repositories to build a security ownership topology (people-to-file), compute bus factor and sensitive-code ownership, and export CSV/JSON for graph databases and visualization. Trigger only when the user explicitly wants a security-oriented ownership or bus-factor analysis grounded in git history (for example: orphaned sensitive code, security maintainers, CODEOWNERS reality checks for risk, sensitive hotspots, or ownership clusters). Do not trigger for general maintainer lists or non-security ownership questions. Originally from OpenAI's curated skills catalog.

openai-security-best-practices

320
from trailofbits/skills-curated

Perform language and framework specific security best-practice reviews and suggest improvements. Trigger only when the user explicitly requests security best practices guidance, a security review/report, or secure-by-default coding help. Trigger only for supported languages (python, javascript/typescript, go). Do not trigger for general code review, debugging, or non-security tasks. Originally from OpenAI's curated skills catalog.