https://github.com/danmolitor/forme
PDF generation with JSX. Page breaks that actually work.
https://github.com/danmolitor/forme
developer-tools jsx pdf pdf-generation react rust typescript wasm
Last synced: about 1 month ago
JSON representation
PDF generation with JSX. Page breaks that actually work.
- Host: GitHub
- URL: https://github.com/danmolitor/forme
- Owner: danmolitor
- License: mit
- Created: 2026-02-17T22:49:17.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-04-29T13:08:41.000Z (about 2 months ago)
- Last Synced: 2026-05-15T19:53:17.715Z (about 1 month ago)
- Topics: developer-tools, jsx, pdf, pdf-generation, react, rust, typescript, wasm
- Language: Rust
- Homepage: https://www.formepdf.com
- Size: 19.3 MB
- Stars: 122
- Watchers: 0
- Forks: 6
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# forme
PDF generation with JSX. Page breaks that actually work.

## Why
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, the browser, or at the edge.
**[Try it in the playground](https://playground.formepdf.com/)**
## Quick Start
```bash
npm install @formepdf/cli @formepdf/react @formepdf/core
```
```tsx
import { Document, Page, View, Text } from '@formepdf/react';
import { renderDocument } from '@formepdf/core';
const pdf = await renderDocument(
Invoice #2024-001
Widget Pro
$49.00
);
// pdf is a Uint8Array: save it, serve it, email it
```
## Dev Server
```bash
npx forme dev invoice.tsx --data sample.json
```
Live preview with debug overlays. Click any element to inspect its computed styles.
## VS Code Extension
Install [Forme PDF Preview](https://marketplace.visualstudio.com/items?itemName=formepdf.forme-pdf) 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
## Features
- **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 dev` shows 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 a `lang` tag. 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'` or `direction: '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-content` distributes 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 `minWidowLines` and `minOrphanLines`.
- **Table overflow**: Table cells with content taller than a page are preserved across page breaks, not silently clipped.
- **Absolute positioning**: `position: 'absolute'` with `top`, `right`, `bottom`, `left` relative to the parent View.
- **Column flex**: `justifyContent` and `alignItems` work in both row and column directions.
- **SVG**: Inline SVG rendering with support for `rect`, `circle`, `ellipse`, `line`, `polyline`, `polygon`, and `path` elements. Supports `opacity`, `fill-opacity`, and `stroke-opacity`. Pass SVG as a `content` string or as JSX children.
- **QR codes**: Built-in `` component. Vector-based, crisp at any zoom level.
- **Barcodes**: Built-in `` component. Code 128, Code 39, EAN-13, EAN-8, Codabar. Vector-based.
- **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 `href` to any ``, ``, ``, or `` for clickable PDF links.
- **Bookmarks**: Add `bookmark` to any element for PDF outline entries. Navigate long documents from the bookmark panel.
- **Inline text styling**: Nest `` inside `` to bold a word, change colors mid-sentence, or apply strikethrough.
- **Images**: JPEG, PNG, and WebP with transparency support. `alt` text for accessibility.
- **CSS shorthands**: `border: "1px solid #000"`, `padding: "8 16"`, `margin: [20, 40]` — CSS-style shorthand strings and arrays parse automatically.
- **Visual style properties**: `opacity` cascades to children, `wordSpacing`, `boxShadow`, ubiquitous `borderRadius` (rounded clipping when `overflow: hidden`), and `background` accepting CSS gradient strings — `linear-gradient(135deg, #667eea, #764ba2)`, `radial-gradient(circle, #10b981, #059669)`. Multi-stop gradients supported.
- **Page backgrounds**: `` for watermark-style overlays. Sizes: `fill` / `cover` / `contain`.
- **Document language**: `` sets the PDF `/Lang` tag 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.
- **Browser rendering**: Import `@formepdf/core/browser` to generate PDFs entirely client-side. Same engine, same templates — no server required.
- **Tailwind CSS**: `tw("p-4 text-lg font-bold bg-blue-500")` converts Tailwind classes to Forme style objects. Full color palette, grid, arbitrary values, negative values, fractions.
- **Fillable forms**: AcroForm components — ``, ``, ``, ``. Fill and flatten for non-editable delivery.
- **PDF/UA accessibility**: `` generates PDF/UA-1 compliant documents with structure tree, tab order, role map, and artifact tagging.
- **PDF/A archival**: `` for long-term preservation. Supports PDF/A-2b and PDF/A-2a.
- **Digital certification**: PKCS#7 certification with X.509 certificates via the `certification` prop or `/v1/certify` API endpoint.
- **PDF redaction**: True content removal with metadata scrubbing. Text-search, regex, presets, and saved templates.
- **PDF merging**: Combine 2-20 PDFs into one via `/v1/merge`.
- **PDF rasterization**: Convert pages to PNG images via `/v1/rasterize`, powered by PDFium.
## Browser Usage
Generate PDFs in the browser with zero server dependencies:
```tsx
import { renderDocument } from '@formepdf/core/browser';
import { Document, Page, Text } from '@formepdf/react';
const pdfBytes = await renderDocument(
Generated in the browser
);
// Download, display in an iframe, or upload
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
window.open(url);
```
Works with Vite, Next.js, Remix, or any bundler that handles WASM. The only difference from server-side usage is the import path.
## Custom Fonts
Register TrueType fonts globally or per-document:
```tsx
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(
Regular text
Bold text
);
```
Or pass fonts directly on the Document:
```tsx
```
Font sources can be file paths, data URIs, or `Uint8Array`. Fonts are automatically subsetted — only glyphs used in the document are embedded.
## Components
| Component | Description |
|-----------|-------------|
| `` | Root element. `title`, `author`, `lang`, `fonts`, `style`. |
| `` | A page. `size`, `margin` (number, string, array, or edges). |
| `` | Container. Flexbox layout. `href`, `bookmark`. |
| `` | Text content. Fonts, sizes, colors. `href`, `bookmark`. |
| `` | JPEG or PNG. `href`, `alt`. Aspect ratio preserved. |
| `` | Table with column definitions. |
| `` | Table row. `header` for repeating on page breaks. |
| `` | Table cell. `colSpan`, `rowSpan`. |
| `` | Inline SVG graphics. `content` string or JSX children. `href`, `alt`. |
| `` | QR code. `data`, `size`, `color`. Vector-based. |
| `` | 1D barcode. `data`, `format`, `width`, `height`, `color`. Code 128, Code 39, EAN-13, EAN-8, Codabar. |
| `` | Arbitrary vector drawing via `draw` callback. |
| `` | Bar chart. `data`, `color`, `showGrid`, `showValues`, `title`. |
| `` | Multi-series line chart. `series`, `labels`, `showPoints`, `showGrid`, `title`. |
| `` | Pie/donut chart. `data`, `donut`, `showLegend`, `title`. |
| `` | Multi-series area chart. `series`, `labels`, `showGrid`, `title`. |
| `` | Scatter plot. `groups`, `xLabel`, `yLabel`, `showLegend`, `dotSize`. |
| `` | Rotated text behind page content. `text`, `fontSize`, `color`, `angle`. |
| `` | Form text input. `name`, `value`, `width`, `multiline`, `password`, `readOnly`. |
| `` | Form checkbox. `name`, `checked`. |
| `` | Form select dropdown. `name`, `options`, `value`, `width`. |
| `` | Form radio button. `name`, `value`, `checked`. |
| `` | Repeating header or footer. |
| `` | Force a page break. |
## Comparison
| | 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 `` |
| 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 | `` component | HTML `` tags |
| Bookmarks | `bookmark` prop on any element | Yes | No |
| QR codes | Built-in `` component | No | Via HTML/JS libraries |
| Barcodes | Built-in `` (5 formats) | No | Via HTML/JS libraries |
| Charts | Engine-native BarChart, LineChart, PieChart, AreaChart, DotPlot | No | Via HTML/JS libraries |
| VS Code extension | Native sidebar panels | No | No |
| Canvas drawing | `` for custom vector graphics | No | HTML Canvas (raster) |
| Watermarks | Built-in `` 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 |
| Browser rendering | Yes (`@formepdf/core/browser`) | Yes (client-side) | No (server only) |
| Tailwind CSS | `tw("p-4 text-lg font-bold")` utility | No | No |
| Fillable forms | AcroForm (TextField, Checkbox, Dropdown, Radio) | No | HTML `` (not PDF forms) |
| PDF/UA accessibility | `` | No | No |
| PDF/A archival | `` | No | No |
| Digital certification | PKCS#7 via `certification` prop or API | No | No |
| Redaction | True content removal + metadata scrubbing | No | No |
| PDF merging | Combine multiple PDFs | No | No |
| Rasterization | PDF → PNG via PDFium | No | No |
| Dependencies | None (WASM) | yoga-layout | Chrome/Chromium |
| Runs in-process | Yes | Yes | No (subprocess) |
## Templates
See the [templates/](./templates) directory for production-ready examples:
- Invoice
- Product Catalog
- Receipt
- Report
- Shipping Label
- Typography
- Grid Dashboard
- Charts Showcase
- Event Ticket
## Tailwind CSS
Style Forme components with Tailwind utility classes via `@formepdf/tailwind`:
```bash
npm install @formepdf/tailwind
```
```tsx
import { tw } from '@formepdf/tailwind';
Invoice
Draft
```
Supports spacing, typography, colors (full Tailwind palette), flexbox, grid, borders, opacity, arbitrary values (`w-[200]`, `bg-[#f00]`), negative values (`-mt-4`), fraction widths (`w-1/2`), and `self-*` alignment.
## Documentation
Full docs at [docs.formepdf.com](https://docs.formepdf.com):
- [Forms](https://docs.formepdf.com/forms) — fillable AcroForm components
- [Accessibility](https://docs.formepdf.com/accessibility) — PDF/UA-1 compliance
- [Archival](https://docs.formepdf.com/archival) — PDF/A compliance
- [Digital Certification](https://docs.formepdf.com/concepts/digital-certification) — PKCS#7 certification
## Contributing
Issues and PRs welcome.
## License
MIT