
React Pdf
- 23 installs
- 167 repo stars
- Updated February 12, 2026
- molefrog/react-pdf-skill
This is a copy of react-pdf by molefrog - installs and ranking accrue to the original listing.
Helps with frontend development tasks.
About
react-pdf is a Claude Code skill for frontend development. It helps solo builders move faster with AI-assisted coding.
- react-pdf
- Frontend Development
- AI-coding skill
React Pdf by the numbers
- 23 all-time installs (skills.sh)
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/molefrog/react-pdf-skill --skill react-pdfAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 23 |
|---|---|
| repo stars | ★ 167 |
| Last updated | February 12, 2026 |
| Repository | molefrog/react-pdf-skill ↗ |
What it does
Helps with frontend development tasks.
Files
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 propertiesassets/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
npm install react @react-pdf/renderer
npm install -D tsx @types/reacttsx 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.
Basic Example
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:
npx tsx my-document.tsxnpx 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:
// 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:
pdftoppm -png -r 200 document.pdf preview
# → preview-1.png, preview-2.png, ...Option 2: PyMuPDF (Python) — fallback if pdftoppm is not available:
pip install pymupdfimport 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
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.
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
{
// 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.
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
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:
npm install lucide-staticimport { 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
<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
<Text render={({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`} />Fixed Headers/Footers
<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
<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 breakCustom Fonts
CRITICAL: All font sources MUST be local file paths. Remote URLs do not work.
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 references/google-fonts.txt to find font URLs, then download locally:
# Find the font URL
grep "^Roboto" 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.ttfIf 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.
npm install twemoji-emojisimport { 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
// 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.
import React from "react";
import { Document, Page, Text, View, StyleSheet, renderToFile } from "@react-pdf/renderer";
const styles = StyleSheet.create({
page: { flexDirection: "column", backgroundColor: "#fff", padding: 40, paddingBottom: 60 },
title: { fontSize: 24, marginBottom: 20, fontWeight: "bold" },
text: { fontSize: 12, lineHeight: 1.5, marginBottom: 8 },
section: { marginBottom: 20 },
// wrap={false} on the parent View makes this block unbreakable —
// if it doesn't fit, it moves entirely to the next page
card: {
border: "1px solid #ccc",
borderRadius: 4,
padding: 12,
marginBottom: 10,
backgroundColor: "#fafafa",
},
// fixed + absolute positioning = footer on every page
footer: {
position: "absolute",
bottom: 25,
left: 40,
right: 40,
textAlign: "center",
fontSize: 9,
color: "#999",
},
});
const filler = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.";
const MyDocument = () => (
<Document>
<Page size="A4" style={styles.page}>
<Text style={styles.title}>Advanced Features Demo</Text>
{/* Generate enough content to trigger page breaks */}
{Array.from({ length: 8 }, (_, i) => (
// wrap={false} — keeps each card together on one page
<View key={i} wrap={false} style={styles.card}>
<Text style={[styles.text, { fontWeight: "bold" }]}>Card {i + 1}</Text>
<Text style={styles.text}>{filler}</Text>
</View>
))}
{/* fixed — renders this Text on every page */}
{/* render prop — gives access to pageNumber / totalPages */}
<Text
style={styles.footer}
fixed
render={({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`}
/>
</Page>
</Document>
);
(async () => {
await renderToFile(<MyDocument />, "./output.pdf");
console.log("PDF saved!");
})();
Component Reference
Document
Root component representing the PDF document.
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | - | Document title metadata |
author | string | - | Document author metadata |
subject | string | - | Document subject metadata |
keywords | string | - | Document keywords metadata |
creator | string | - | Application that created the document |
producer | string | - | PDF producer |
pdfVersion | string | "1.3" | PDF version |
language | string | - | Default document language |
pageMode | string | - | Display mode: useNone, useOutlines, useThumbs, fullScreen, useOC, useAttachments |
pageLayout | string | - | Page layout: singlePage, oneColumn, twoColumnLeft, twoColumnRight, twoPageLeft, twoPageRight |
onRender | function | - | Callback after rendering with { blob } |
Page
Represents a single page in the document.
| Prop | Type | Default | Description |
|---|---|---|---|
size | string/array/object | "A4" | Page size (A4, Letter, Legal, etc.) or [width, height] or {width, height} |
orientation | string | "portrait" | Page orientation: portrait, landscape |
wrap | boolean | true | Enable automatic page wrapping |
style | object/array | - | Page styling |
debug | boolean | false | Show bounding box |
dpi | number | 72 | Custom DPI setting |
id | string | - | Destination ID for internal links |
View
Container component for layout, similar to div.
| Prop | Type | Default | Description |
|---|---|---|---|
wrap | boolean | true | Enable page wrapping |
style | object/array | - | View styling |
render | function | - | Dynamic content: ({ pageNumber, totalPages, subPageNumber, subPageTotalPages }) => content |
debug | boolean | false | Show bounding box |
fixed | boolean | false | Render on all wrapped pages |
break | boolean | false | Force page break before this element |
minPresenceAhead | number | - | Minimum space ahead before breaking |
id | string | - | Destination ID for internal links |
Text
Displays text content.
| Prop | Type | Default | Description |
|---|---|---|---|
wrap | boolean | true | Enable page wrapping |
style | object/array | - | Text styling |
render | function | - | Dynamic content function |
debug | boolean | false | Show bounding box |
fixed | boolean | false | Render on all wrapped pages |
hyphenationCallback | function | - | Custom hyphenation |
orphans | number | - | Minimum lines at bottom of page |
widows | number | - | Minimum lines at top of page |
id | string | - | Destination ID |
Link
Creates hyperlinks.
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | - | URL or internal destination (prefix with #) |
wrap | boolean | true | Enable page wrapping |
style | object/array | - | Link styling |
debug | boolean | false | Show bounding box |
Image
Displays images.
| Prop | Type | Default | Description |
|---|---|---|---|
src / source | string/object/function | - | Image source: URL, file path, Buffer, or async function |
style | object/array | - | Image styling |
debug | boolean | false | Show bounding box |
cache | boolean | true | Enable image caching |
Note
Adds annotation notes.
| Prop | Type | Default | Description |
|---|---|---|---|
children | string | - | Note text content |
style | object/array | - | Note styling |
Canvas
Freeform drawing component.
| Prop | Type | Default | Description |
|---|---|---|---|
paint | function | - | Painter function: (painter, width, height) => void |
style | object/array | - | Canvas styling |
debug | boolean | false | Show bounding box |
Svg
SVG container component.
| Prop | Type | Default | Description |
|---|---|---|---|
width | string/number | - | SVG width |
height | string/number | - | SVG height |
viewBox | string | - | SVG viewBox |
preserveAspectRatio | string | - | Aspect ratio handling |
style | object/array | - | SVG styling |
SVG Shape Elements
| Element | Key Props |
|---|---|
Line | x1, y1, x2, y2, stroke, strokeWidth |
Rect | x, y, width, height, rx, ry, fill, stroke |
Circle | cx, cy, r, fill, stroke |
Ellipse | cx, cy, rx, ry, fill, stroke |
Polygon | points, fill, stroke |
Polyline | points, fill, stroke |
Path | d, fill, stroke |
Text | x, y, fill, textAnchor |
Tspan | x, y, dx, dy |
G | transform (group container) |
Defs | (definitions container) |
ClipPath | id (clipping path) |
LinearGradient | id, x1, y1, x2, y2 |
RadialGradient | id, cx, cy, r, fx, fy |
Stop | offset, stopColor, stopOpacity |
SVG Presentation Attributes
color, dominantBaseline, fill, fillOpacity, fillRule, opacity, stroke, strokeWidth, strokeOpacity, strokeLinecap, strokeLinejoin, strokeDasharray, transform, textAnchor, visibility
Supported CSS Properties
Flexbox
alignContent, alignItems, alignSelf, flex, flexDirection, flexWrap, flexFlow, flexGrow, flexShrink, flexBasis, justifyContent, gap, rowGap, columnGap
Layout
bottom, display, left, position, right, top, overflow, zIndex
Dimensions
height, maxHeight, maxWidth, minHeight, minWidth, width
Color
backgroundColor, color, opacity
Text
fontSize, fontFamily, fontStyle, fontWeight, letterSpacing, lineHeight, maxLines, textAlign, textDecoration, textDecorationColor, textDecorationStyle, textIndent, textOverflow, textTransform
Margins
margin, marginTop, marginRight, marginBottom, marginLeft, marginHorizontal, marginVertical
Padding
padding, paddingTop, paddingRight, paddingBottom, paddingLeft, paddingHorizontal, paddingVertical
Borders
border, borderTop, borderRight, borderBottom, borderLeft, borderColor, borderTopColor, borderRightColor, borderBottomColor, borderLeftColor, borderStyle, borderTopStyle, borderRightStyle, borderBottomStyle, borderLeftStyle, borderWidth, borderTopWidth, borderRightWidth, borderBottomWidth, borderLeftWidth, borderRadius, borderTopLeftRadius, borderTopRightRadius, borderBottomRightRadius, borderBottomLeftRadius
Transformations
rotate, scale, scaleX, scaleY, translate, translateX, translateY, skew, skewX, skewY, matrix, transformOrigin
Object Fit
objectFit, objectPosition