Skip to main content
If you are hitting page break issues, broken flex layouts across pages, or missing table header repetition in react-pdf, Forme fixes all of these. The two libraries share a similar component API, so migration is mostly renaming imports. This guide covers the differences and what to watch for.

Component mapping

react-pdfFormeNotes
<Document><Document>Same
<Page><Page>Same props, same behavior
<View><View>Same
<Text><Text>Same
<Image><Image>Same API, supports file paths and data URIs
<Link><Text href="...">Use the href prop on <Text> or <View> to create clickable links
<Note>Not yet supported-
<Canvas>Not yet supported-
<SVG><Svg>SVG content passed as a string via the content prop. Supports basic shapes and paths.

Import changes

react-pdf:
import { Document, Page, View, Text, Image, StyleSheet } from '@react-pdf/renderer';
Forme:
import { Document, Page, View, Text, Image } from '@formepdf/react';
Forme also has StyleSheet.create() for familiarity:
import { StyleSheet } from '@formepdf/react';

const styles = StyleSheet.create({
  heading: { fontSize: 24, fontWeight: 700 },
});
It works the same way as react-pdf’s version. It’s an identity function that provides TypeScript autocomplete.

Style differences

Most style properties are the same between react-pdf and Forme. Key differences:
Propertyreact-pdfForme
fontWeight"bold" or number"bold", "normal", or number (100-900)
borderWidthSingle numberNumber or { top, right, bottom, left }
borderColorSingle stringString or { top, right, bottom, left }
borderRadiusSingle numberNumber or { topLeft, topRight, bottomRight, bottomLeft }
margin"auto" supported"auto" not supported (use flexbox alignment instead)
position"absolute" supportedposition: "absolute" supported in both. Forme also has <Fixed> for repeating headers/footers, which automatically adjusts the content area.

Rendering

react-pdf:
import { renderToBuffer } from '@react-pdf/renderer';
const buffer = await renderToBuffer(<MyDocument />);
Forme:
import { renderDocument } from '@formepdf/core';
const pdfBytes = await renderDocument(<MyDocument />);
Both return PDF bytes. Forme returns a Uint8Array, react-pdf returns a Node.js Buffer.

Tables

react-pdf does not have a built-in Table component. Most projects use <View> with row/column flex layout to simulate tables. Forme has first-class table support: react-pdf (common pattern):
<View style={{ flexDirection: 'row', borderBottom: '1px solid #ccc' }}>
  <View style={{ width: '50%', padding: 8 }}><Text>Name</Text></View>
  <View style={{ width: '50%', padding: 8 }}><Text>Price</Text></View>
</View>
Forme:
<Table columns={[{ width: { fraction: 0.5 } }, { width: { fraction: 0.5 } }]}>
  <Row header>
    <Cell style={{ padding: 8 }}><Text>Name</Text></Cell>
    <Cell style={{ padding: 8 }}><Text>Price</Text></Cell>
  </Row>
</Table>
The Forme version gets automatic header repetition on page breaks and correct row-level page splitting.

Fixed headers and footers

react-pdf:
<Page>
  <View fixed style={{ position: 'absolute', top: 0, left: 0, right: 0 }}>
    <Text>Header</Text>
  </View>
</Page>
Forme:
<Page>
  <Fixed position="header">
    <Text>Header</Text>
  </Fixed>
</Page>
In Forme, fixed elements automatically reduce the content area, so body content never overlaps with headers or footers. In react-pdf, you need to manually add padding to avoid overlap.

Page numbers

react-pdf:
<Text render={({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`} />
Forme:
<Text>Page {'{{pageNumber}}'} of {'{{totalPages}}'}</Text>
Both approaches produce the same result. Forme uses template placeholders instead of a render callback.

What works better in Forme

  1. Page breaks. Flex containers, tables, and text all break correctly across pages. In react-pdf, flex layouts produce incorrect proportions after page splits.
  2. Table header repetition. Mark a row as header and it repeats on every page. No workarounds needed.
  3. Dev server. forme dev gives you live preview with debug overlays and click-to-inspect. react-pdf requires rendering to a file and opening it manually.
  4. Speed. Forme’s Rust/WASM engine renders in milliseconds. react-pdf is typically 5-10x slower for complex documents.
  5. Dependencies. Forme is a single WASM binary with no native dependencies. react-pdf depends on yoga-layout (native binary).
  6. Links. Add href to any <Text> or <View> to create clickable PDF links. No separate <Link> component needed.
  7. Bookmarks. Add bookmark to any <Text> or <View> to create PDF outline entries. Readers can navigate long documents from the bookmark panel.
  8. Inline text styling. Nest <Text> inside <Text> to style individual words or spans. Bold a single word, change colors mid-sentence, or apply strikethrough to a price.
  9. QR codes. Built-in <QrCode> component renders vector-based QR codes. react-pdf has no equivalent.
  10. Barcodes. Built-in <Barcode> component supports Code 128, Code 39, EAN-13, EAN-8, and Codabar. react-pdf has no equivalent.
  11. Text overflow. textOverflow: 'ellipsis' truncates single-line text with ”…” when it exceeds available width. react-pdf does not support text truncation.
  12. Font fallback chains. fontFamily: "Inter, Helvetica" tries each font in order. react-pdf only accepts a single family name.

What works in react-pdf but not Forme (yet)

Be honest about these gaps before migrating:
  1. <Canvas> component. react-pdf’s <Canvas> uses a render callback with the raw PDF page object. Forme’s <Canvas> provides a recording context with a Canvas-like API (moveTo, lineTo, arc, rect, fill, stroke, etc.).
  2. <Note> component. react-pdf supports PDF annotations via <Note>. Forme does not support this yet.
  3. Emoji rendering. react-pdf handles emoji via system fonts. Forme does not have special emoji support.
  4. margin: "auto". react-pdf supports margin: "auto" for centering. In Forme, use flexbox alignment (justifyContent: 'center', alignItems: 'center') instead.

Migration checklist

  1. Replace @react-pdf/renderer imports with @formepdf/react and @formepdf/core
  2. Update StyleSheet import from @react-pdf/renderer to @formepdf/react (works the same way)
  3. Replace fixed prop + absolute positioning with <Fixed position="header"> or <Fixed position="footer">
  4. Replace render callbacks for page numbers with {{pageNumber}} / {{totalPages}} placeholders
  5. Convert View-based table layouts to <Table>, <Row>, <Cell> components
  6. Convert <SVG> elements to <Svg> with SVG markup in the content prop
  7. Replace <Link> components with <Text href="..."> equivalents
  8. Test page break behavior, especially for tables and flex layouts