@json-render/react-pdf

PDF document renderer. Turn JSON specs into PDFs using @react-pdf/renderer.

Install

npm install @json-render/core @json-render/react-pdf

See the React PDF example for a full working example.

schema

The PDF element schema for document specs. Use with defineCatalog from core.

import { defineCatalog } from '@json-render/core';
import { schema, standardComponentDefinitions } from '@json-render/react-pdf';

const catalog = defineCatalog(schema, {
  components: standardComponentDefinitions,
});

Render Functions

Server-side functions for producing PDF output. All accept a spec and optional RenderOptions.

import { renderToBuffer, renderToStream, renderToFile } from '@json-render/react-pdf';

const buffer = await renderToBuffer(spec);

const stream = await renderToStream(spec);
stream.pipe(res);

await renderToFile(spec, './output.pdf');

RenderOptions

interface RenderOptions {
  registry?: ComponentRegistry;
  includeStandard?: boolean;  // default: true
  state?: Record<string, unknown>;
}
OptionDescription
registryCustom component map (merged with standard components)
includeStandardInclude built-in standard components (default: true)
stateInitial state for $state / $cond dynamic prop resolution

defineRegistry

Create a type-safe component registry from a catalog. Components receive { props, children, emit, bindings, loading }.

import { defineRegistry } from '@json-render/react-pdf';
import { View, Text } from '@react-pdf/renderer';

const { registry } = defineRegistry(catalog, {
  components: {
    Badge: ({ props }) => (
      <View style={{ backgroundColor: props.color ?? '#e5e7eb', padding: 4, borderRadius: 4 }}>
        <Text style={{ fontSize: 10 }}>{props.label}</Text>
      </View>
    ),
  },
});

const buffer = await renderToBuffer(spec, { registry });

createRenderer

Create a standalone renderer component wired to state, actions, and validation.

import { createRenderer } from '@json-render/react-pdf';

const PDFRenderer = createRenderer(catalog, components);
interface CreateRendererProps {
  spec: Spec | null;
  state?: Record<string, unknown>;
  onAction?: (actionName: string, params?: Record<string, unknown>) => void;
  onStateChange?: (path: string, value: unknown) => void;
  loading?: boolean;
  fallback?: ComponentRenderer;
}

Renderer

The main component that renders a spec to @react-pdf/renderer elements.

interface RendererProps {
  spec: Spec | null;
  registry?: ComponentRegistry;
  includeStandard?: boolean;  // default: true
  loading?: boolean;
  fallback?: ComponentRenderer;
}

Standard Components

Document Structure

Document

Top-level PDF wrapper. Must be the root element. Children must be Page components.

{
  title: string | null;
  author: string | null;
  subject: string | null;
}

Page

A page in the document with configurable size, orientation, and margins.

{
  size: "A4" | "A3" | "A5" | "LETTER" | "LEGAL" | "TABLOID" | null;
  orientation: "portrait" | "landscape" | null;
  marginTop: number | null;
  marginBottom: number | null;
  marginLeft: number | null;
  marginRight: number | null;
  backgroundColor: string | null;
}

Layout

View

Generic container with padding, margin, background, border, and flex alignment.

{
  padding: number | null;
  paddingTop: number | null;
  paddingBottom: number | null;
  paddingLeft: number | null;
  paddingRight: number | null;
  margin: number | null;
  backgroundColor: string | null;
  borderWidth: number | null;
  borderColor: string | null;
  borderRadius: number | null;
  flex: number | null;
  alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
  justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
}

Row

Horizontal flex layout with optional wrapping.

{
  gap: number | null;
  alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
  justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
  padding: number | null;
  flex: number | null;
  wrap: boolean | null;
}

Column

Vertical flex layout.

{
  gap: number | null;
  alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
  justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
  padding: number | null;
  flex: number | null;
}

Content

Heading

h1-h4 heading text with configurable color and alignment.

{
  text: string;
  level: "h1" | "h2" | "h3" | "h4" | null;
  color: string | null;
  align: "left" | "center" | "right" | null;
}

Text

Body text with full styling control.

{
  text: string;
  fontSize: number | null;
  color: string | null;
  align: "left" | "center" | "right" | null;
  fontWeight: "normal" | "bold" | null;
  fontStyle: "normal" | "italic" | null;
  lineHeight: number | null;
}

Image

Image from a URL with optional dimensions and fit.

{
  src: string;
  width: number | null;
  height: number | null;
  objectFit: "contain" | "cover" | "fill" | "none" | null;
}

Link

Hyperlink with visible text.

{
  text: string;
  href: string;
  fontSize: number | null;
  color: string | null;
}

Data

Table

Data table with typed columns and string rows. Supports header styling and striped rows.

{
  columns: { header: string; width?: string; align?: "left" | "center" | "right" }[];
  rows: string[][];
  headerBackgroundColor: string | null;
  headerTextColor: string | null;
  borderColor: string | null;
  fontSize: number | null;
  striped: boolean | null;
}

List

Ordered or unordered list.

{
  items: string[];
  ordered: boolean | null;
  fontSize: number | null;
  color: string | null;
  spacing: number | null;
}

Decorative

Divider

Horizontal line separator.

{
  color: string | null;
  thickness: number | null;
  marginTop: number | null;
  marginBottom: number | null;
}

Spacer

Empty vertical space.

{
  height: number | null;
}

Page-Level

PageNumber

Renders current page number and total pages. Format uses {pageNumber} and {totalPages} placeholders.

{
  format: string | null;    // default: "{pageNumber} / {totalPages}"
  fontSize: number | null;
  color: string | null;
  align: "left" | "center" | "right" | null;
}

Server-Safe Import

Import schema and catalog definitions without pulling in React or @react-pdf/renderer:

import { schema, standardComponentDefinitions } from '@json-render/react-pdf/server';

Sub-path Exports

ExportDescription
@json-render/react-pdfFull package: schema, renderer, components, render functions
@json-render/react-pdf/serverSchema and catalog definitions only (no React)
@json-render/react-pdf/catalogStandard component definitions and types
@json-render/react-pdf/renderServer-side render functions only

Types

ExportDescription
ReactPdfSchemaSchema type for PDF specs
ReactPdfSpecSpec type for PDF documents
RenderOptionsOptions for render functions
ComponentContextTyped component render function context
ComponentFnComponent render function type
StandardComponentDefinitionsType of the standard component definitions object
StandardComponentProps<K>Inferred props type for a standard component by name