react-pdf
vercel-labs/json-render
Render PDF documents from JSON specs using React components.
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 generate PDFs programmatically from structured data, with support for layouts, tables, images, and custom components.
- Render JSON specs to PDF buffers, streams, or files
- Support standard components: Document, Page, View, Text, Heading, Table, Image, List, Link, and more
- Define custom components with Zod schemas and React implementations
- Control state with StateStore for dynamic content
- Server-safe imports for schema and catalog without React dependencies
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 @json-render/core and @json-render/react-pdf via npm
- 2.Define a JSON spec with a root element and component tree
- 3.Import renderToBuffer, renderToStream, or renderToFile from @json-render/react-pdf
- 4.Call the render function with your spec to generate PDF output
- 5.Optionally pass a registry with custom components or state store for dynamic content
Use cases
- Generate invoices or receipts from order data
- Create dynamic reports with tables and charts from JSON data
- Build templated documents (certificates, contracts) from specifications
- Render multi-page documents with headers, footers, and page numbers
- Combine custom branded components with standard PDF layouts
- Backend developers generating PDFs programmatically
- Full-stack engineers building document generation features
- Teams using json-render for declarative UI specifications
- Applications needing server-side PDF rendering without browser dependencies
react-pdf FAQ
Three formats: renderToBuffer (in-memory Buffer), renderToStream (Readable stream for HTTP responses), and renderToFile (direct file write).
Yes, define custom components using defineCatalog and defineRegistry with Zod schemas, then pass the registry to render functions.
Use createStateStore to manage state, pass it to render functions, and reference state paths in your JSON spec.
Yes, import from @json-render/react-pdf/server to get schema and catalog without pulling in React dependencies.
Page component supports standard sizes (A4, LETTER) and orientation settings via props.
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:
Nested lists can set repeat.statePath to { "$item": "field" } inside an enclosing repeat.
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
Convert JSON timeline specs into videos using Remotion compositions.

remotion-best-practices
Domain-specific best practices and patterns for building videos with Remotion and 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.