react-pdf
vercel-labs/json-render
Generate PDF documents from JSON specs using React components and @react-pdf/renderer.
What is react-pdf?
@json-render/react-pdf is a React-based PDF renderer that converts JSON specifications into PDF documents. Use it when you need to programmatically generate PDFs from structured data, render to buffers/streams/files, or build custom PDF layouts with React components.
- Render JSON specs to PDF buffers, streams, or files with three simple APIs
- Support standard PDF components (Document, Page, Table, Text, Image, List, etc.)
- Define custom components with Zod schemas and React implementations
- Control state with external StateStore for dynamic content
- Layout with flexbox (Row, Column) and spacing primitives
- Generate multi-page documents with page numbers and headers/footers
How to install react-pdf
npx skills add https://github.com/vercel-labs/json-render --skill react-pdf- Node.js environment
- npm or yarn package manager
- @json-render/core and @json-render/react-pdf installed
How to use react-pdf
- 1.Install dependencies: npm install @json-render/core @json-render/react-pdf
- 2.Define a JSON spec with root element and component tree (Document → Page → content)
- 3.Choose a render function: renderToBuffer (memory), renderToStream (HTTP), or renderToFile (disk)
- 4.Call the render function with your spec and optional registry/state/handlers
- 5.For custom components, define a catalog with Zod schemas and React implementations, then pass the registry to render
Use cases
- Generate invoices, receipts, or reports from structured JSON data
- Create dynamic PDF exports in web applications by piping streams to HTTP responses
- Build reusable PDF templates with custom components and styling
- Render tables and lists from database queries into formatted PDF documents
- Generate certificates or documents with variable content from external state
- Backend developers building PDF generation APIs
- Full-stack developers adding PDF export features to web apps
- Document automation engineers creating templated reports
- Node.js/TypeScript developers working with json-render ecosystem
react-pdf FAQ
renderToBuffer returns a complete PDF in memory (best for small docs or APIs), renderToStream returns a readable stream (ideal for piping to HTTP responses), and renderToFile writes directly to disk (best for batch processing).
Yes. Define custom components in a catalog using Zod schemas for props validation, implement them as React components, and pass the registry to the render function.
Use the optional state parameter when calling render functions, or create a StateStore with createStateStore for controlled state management across your spec.
No. Import from @json-render/react-pdf/server to access schema and catalog definitions without pulling in React dependencies.
Page component supports standard sizes (A4, LETTER) and orientations (portrait, landscape), with configurable margins. Use Row/Column for flexbox layout and View for containers with padding, margins, and borders.
Full instructions (SKILL.md)
Source of truth, from vercel-labs/json-render.
name: react-pdf description: React PDF renderer for json-render. Use when generating PDF documents from JSON specs, working with @json-render/react-pdf, or rendering specs to PDF buffers/streams/files.
@json-render/react-pdf
React PDF renderer that generates PDF documents from JSON specs using @react-pdf/renderer.
Installation
npm install @json-render/core @json-render/react-pdf
Quick Start
import { renderToBuffer } from "@json-render/react-pdf";
import type { Spec } from "@json-render/core";
const spec: Spec = {
root: "doc",
elements: {
doc: { type: "Document", props: { title: "Invoice" }, children: ["page"] },
page: {
type: "Page",
props: { size: "A4" },
children: ["heading", "table"],
},
heading: {
type: "Heading",
props: { text: "Invoice #1234", level: "h1" },
children: [],
},
table: {
type: "Table",
props: {
columns: [
{ header: "Item", width: "60%" },
{ header: "Price", width: "40%", align: "right" },
],
rows: [
["Widget A", "$10.00"],
["Widget B", "$25.00"],
],
},
children: [],
},
},
};
const buffer = await renderToBuffer(spec);
Render APIs
import { renderToBuffer, renderToStream, renderToFile } from "@json-render/react-pdf";
// In-memory buffer
const buffer = await renderToBuffer(spec);
// Readable stream (pipe to HTTP response)
const stream = await renderToStream(spec);
stream.pipe(res);
// Direct to file
await renderToFile(spec, "./output.pdf");
All render functions accept an optional second argument: { registry?, state?, handlers? }.
Standard Components
| Component | Description |
|---|---|
Document | Top-level PDF wrapper (must be root) |
Page | Page with size (A4, LETTER), orientation, margins |
View | Generic container (padding, margin, background, border) |
Row, Column | Flex layout with gap, align, justify |
Heading | h1-h4 heading text |
Text | Body text (fontSize, color, weight, alignment) |
Image | Image from URL or base64 |
Link | Hyperlink with text and href |
Table | Data table with typed columns and rows |
List | Ordered or unordered list |
Divider | Horizontal line separator |
Spacer | Empty vertical space |
PageNumber | Current page number and total pages |
Custom Catalog
import { defineCatalog } from "@json-render/core";
import { schema, defineRegistry, renderToBuffer } from "@json-render/react-pdf";
import { standardComponentDefinitions } from "@json-render/react-pdf/catalog";
import { z } from "zod";
const catalog = defineCatalog(schema, {
components: {
...standardComponentDefinitions,
Badge: {
props: z.object({ label: z.string(), color: z.string().nullable() }),
slots: [],
description: "A colored badge label",
},
},
actions: {},
});
const { registry } = defineRegistry(catalog, {
components: {
Badge: ({ props }) => (
<View style={{ backgroundColor: props.color ?? "#e5e7eb", padding: 4 }}>
<Text>{props.label}</Text>
</View>
),
},
});
const buffer = await renderToBuffer(spec, { registry });
External Store (Controlled Mode)
Pass a StateStore for full control over state:
import { createStateStore } from "@json-render/react-pdf";
const store = createStateStore({ invoice: { total: 100 } });
store.set("/invoice/total", 200);
Server-Safe Import
Import schema and catalog without pulling in React:
import { schema, standardComponentDefinitions } from "@json-render/react-pdf/server";
Related skills
More from vercel-labs/json-render and the wider catalog.

react-three-fiber
Render interactive 3D scenes from JSON specs using React Three Fiber and Three.js

redux
Redux adapter for json-render's StateStore interface. Use when integrating json-render with Redux or Redux Toolkit for state management via @json-render/redux.

remotion
Remotion renderer for json-render that turns JSON timeline specs into videos. Use when working with @json-render/remotion, building video compositions from JSON, creating video catalogs, or rendering AI-generated video timelines.

remotion-best-practices
Best practices for Remotion - Video creation in React

shadcn
36 pre-built shadcn/ui components for json-render with Radix UI + Tailwind CSS.

shadcn-svelte
Pre-built shadcn-svelte components for json-render Svelte apps. Use when working with @json-render/shadcn-svelte, adding standard UI components to a Svelte catalog, or building Svelte web UIs with shadcn-svelte + Tailwind CSS components.