PDF generation with JSX. Page breaks that actually work.
Every PDF tool makes you choose: fight with CSS page breaks or use an editor that can't handle dynamic data. Forme is a layout engine built for pages. No headless browser. No Chrome. Renders in milliseconds. Runs anywhere Node runs.
npm install @formepdf/cli @formepdf/react @formepdf/coreimport { Document, Page, View, Text } from '@formepdf/react';
import { renderDocument } from '@formepdf/core';
const pdf = await renderDocument(
<Document>
<Page size="Letter" margin={36}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Invoice #2024-001</Text>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 24 }}>
<Text>Widget Pro</Text>
<Text>$49.00</Text>
</View>
</Page>
</Document>
);
// pdf is a Uint8Array: save it, serve it, email itnpx forme dev invoice.tsx --data sample.jsonLive preview with debug overlays. Click any element to inspect its computed styles.
Install Forme PDF Preview from the VS Code Marketplace.
- Live PDF preview in a webview panel
- Component tree in the sidebar with hover-to-highlight
- Inspector panel with box model, computed styles, and source navigation
- Click any element on the canvas to select it in the tree and inspector
- Page-native layout: Content flows into pages, not onto an infinite canvas. Page breaks happen at the right place, every time.
- React components: Document, Page, View, Text, Image, Table. If you know React, you know Forme.
- Live preview:
forme devshows your PDF updating in real time as you edit. - Click-to-inspect: Select any element in the browser or VS Code to see its box model, computed styles, and position.
- Debug overlays: Toggle bounding boxes, margins, and page break points.
- Fast: Rust engine compiled to WASM. Renders in milliseconds, not seconds.
- OpenType shaping: Real GSUB/GPOS shaping via rustybuzz. Ligatures (fi, ffi), kerning (AV), and contextual forms render correctly with custom fonts.
- Optimal line breaking: Knuth-Plass algorithm (the same one TeX uses) considers the entire paragraph to minimize awkward spacing. Falls back to greedy when needed.
- Hyphenation: Automatic hyphenation in 35+ languages. Set
hyphens: 'auto'and alangtag. Uses the hypher crate with language-specific dictionaries. - BiDi text: Right-to-left text (Arabic, Hebrew) with automatic direction detection. Mixed LTR/RTL paragraphs reorder correctly. Set
direction: 'rtl'ordirection: 'auto'. - CSS Grid: 2D grid layout with
display: 'grid'. Fixed, fractional (fr), and auto track sizing. Explicit placement, auto-placement, column/row spanning, and row-level page breaks. - Flex wrap + align-content: Flex containers wrap across pages correctly.
align-contentdistributes wrapped lines (center,space-between,space-around,space-evenly,flex-end,stretch). - Widow/orphan control: Text paragraphs never leave a single orphan line at the bottom of a page or a single widow line at the top. Configurable via
minWidowLinesandminOrphanLines. - Table overflow: Table cells with content taller than a page are preserved across page breaks, not silently clipped.
- Absolute positioning:
position: 'absolute'withtop,right,bottom,leftrelative to the parent View. - Column flex:
justifyContentandalignItemswork in both row and column directions. - SVG: Inline SVG rendering with support for
rect,circle,ellipse,line,polyline,polygon, andpathelements. - QR codes: Built-in
<QrCode>component. Vector-based, crisp at any zoom level. - Text overflow:
textOverflow: 'ellipsis'truncates single-line text with "..." when it exceeds available width. Also supports'clip'. - Builtin Unicode support: Noto Sans is bundled - Cyrillic, Greek, and other non-Latin scripts work out of the box without registering fonts.
- Font fallback chains:
fontFamily: "Inter, Helvetica"tries each font in order, falling back automatically. - Custom fonts: TrueType font embedding with automatic subsetting.
- Links: Add
hrefto any<Text>,<View>,<Image>, or<Svg>for clickable PDF links. - Bookmarks: Add
bookmarkto any element for PDF outline entries. Navigate long documents from the bookmark panel. - Inline text styling: Nest
<Text>inside<Text>to bold a word, change colors mid-sentence, or apply strikethrough. - Images: JPEG, PNG, and WebP with transparency support.
alttext for accessibility. - CSS shorthands:
border: "1px solid #000",padding: "8 16",margin: [20, 40]— CSS-style shorthand strings and arrays parse automatically. - Document language:
<Document lang="en-US">sets the PDF/Langtag for accessibility. - Dynamic page numbers:
{{pageNumber}}and{{totalPages}}in any text element. - Embedded data: Attach structured JSON to any PDF. Recipients can extract the original data programmatically — invoices carry their line items, reports carry their datasets.
Register TrueType fonts globally or per-document:
import { Font, Document, Text } from '@formepdf/react';
import { renderDocument } from '@formepdf/core';
// Global registration (works like react-pdf)
Font.register({
family: 'Inter',
src: './fonts/Inter-Regular.ttf',
});
Font.register({
family: 'Inter',
src: './fonts/Inter-Bold.ttf',
fontWeight: 'bold',
});
const pdf = await renderDocument(
<Document>
<Text style={{ fontFamily: 'Inter', fontSize: 16 }}>
Regular text
</Text>
<Text style={{ fontFamily: 'Inter', fontSize: 16, fontWeight: 'bold' }}>
Bold text
</Text>
</Document>
);Or pass fonts directly on the Document:
<Document fonts={[
{ family: 'Roboto', src: './fonts/Roboto-Regular.ttf' },
{ family: 'Roboto', src: './fonts/Roboto-Italic.ttf', fontStyle: 'italic' },
]}>Font sources can be file paths, data URIs, or Uint8Array. Fonts are automatically subsetted — only glyphs used in the document are embedded.
| Component | Description |
|---|---|
<Document> |
Root element. title, author, lang, fonts, style. |
<Page> |
A page. size, margin (number, string, array, or edges). |
<View> |
Container. Flexbox layout. href, bookmark. |
<Text> |
Text content. Fonts, sizes, colors. href, bookmark. |
<Image> |
JPEG or PNG. href, alt. Aspect ratio preserved. |
<Table> |
Table with column definitions. |
<Row> |
Table row. header for repeating on page breaks. |
<Cell> |
Table cell. colSpan, rowSpan. |
<Svg> |
Inline SVG graphics. href, alt. |
<QrCode> |
QR code. data, size, color. Vector-based. |
<Canvas> |
Arbitrary vector drawing via draw callback. |
<BarChart> |
Bar chart. data, color, showGrid, showValues. |
<LineChart> |
Line chart. data, color, showDots, showArea. |
<PieChart> |
Pie/donut chart. data, innerRadius, showLabels. |
<Watermark> |
Rotated text behind page content. text, fontSize, color, angle. |
<Fixed> |
Repeating header or footer. |
<PageBreak> |
Force a page break. |
| Forme | react-pdf | Puppeteer | |
|---|---|---|---|
| Page breaks | Page-native (widow/orphan aware) | Broken for 7 years | CSS page-break (fragile) |
| Table header repetition | Automatic on every page | Not built in | Inconsistent <thead> |
| Line breaking | Knuth-Plass optimal (TeX algorithm) | Greedy | Browser engine |
| Hyphenation | 35+ languages, automatic | Via callback | Browser engine |
| Text shaping | OpenType GSUB/GPOS (ligatures, kerning) | Basic | Full browser shaping |
| BiDi text | RTL, mixed LTR/RTL, auto-detection | No | Full browser BiDi |
| CSS Grid | display: 'grid' with fr/auto/fixed tracks |
No | Full CSS Grid |
| Live preview | Built-in dev server | Render to file | Run script, open file |
| Click-to-inspect | VS Code, Cursor, WebStorm | No | No |
| Render speed | ~28ms (4-page report) | ~100-500ms | ~1-5s (Chrome boot) |
| Memory per render | No browser process (WASM) | ~50-100MB | ~50-200MB |
| SVG | Basic shapes and paths | Yes | Full browser SVG |
| Links | href prop on Text/View/Image/Svg |
<Link> component |
HTML <a> tags |
| Bookmarks | bookmark prop on any element |
Yes | No |
| QR codes | Built-in <QrCode> component |
No | Via HTML/JS libraries |
| Charts | Built-in BarChart, LineChart, PieChart | No | Via HTML/JS libraries |
| VS Code extension | Native sidebar panels | No | No |
| Canvas drawing | <Canvas draw={...}> for custom vector graphics |
No | HTML Canvas (raster) |
| Watermarks | Built-in <Watermark> component |
No | Manual positioning |
| Embedded data | Attach JSON to PDF, extract later | No | No |
| Text overflow | textOverflow: 'ellipsis' |
No | CSS text-overflow |
| Font fallback | fontFamily: "Inter, Helvetica" |
Single family only | Full CSS font stack |
| Custom fonts | TTF with OpenType shaping | Yes | Yes |
| Dependencies | None (WASM) | yoga-layout | Chrome/Chromium |
| Runs in-process | Yes | Yes | No (subprocess) |
See the templates/ directory for production-ready examples:
- Invoice
- Product Catalog
- Receipt
- Report
- Shipping Label
- Typography
- Grid Dashboard
- Event Ticket
Full docs at docs.formepdf.com
Issues and PRs welcome.
MIT
