Introduction to takumi-pdf
Render JSX to paged, selectable-text PDF with takumi-pdf.
takumi-pdf renders the same JSX, Tailwind classes, and node trees as image output. It writes a paged vector PDF instead. It ships as a WebAssembly module. It runs on Node.js, Bun, and Cloudflare Workers without Chromium.
- Page breaks honor
break-before: page,break-after: page, andbreak-inside: avoid. - Headers and footers repeat on every page, with page counters.
- Text stays selectable and searchable. Fonts embed as subsets.
- Links and metadata carry into the output.
outline: truebuilds bookmarks from headings. - Attachments embed files, including Factur-X e-invoice XML.
- Tagged PDF is on by default. PDF/A-2, A-3, A-4, and PDF/UA-1 pass veraPDF.
- Arabic, bidi text, CJK, Devanagari, and emoji shape correctly.
- Gradients,
box-shadow, transforms, and color filters stay vector, conic gradients included. - 1.5 MB of gzip wasm fits the Cloudflare Workers free plan.
npm i takumi-pdfRender a document
import { } from "takumi-pdf";
import { } from "@takumi-rs/helpers";
import { } from "node:fs/promises";
const = await (< ={} />, {
// A4 portrait with a 48px margin is the default
: "a4",
: await (["Inter"]),
: (
< ="flex w-full justify-center text-[10px] text-gray-500">
Page < ="pageNumber" /> of < ="totalPages" />
</>
),
});
await ("invoice.pdf", );render() accepts JSX, HTML strings, or JSON node trees. It returns Uint8Array PDF bytes. Content lays out at the page's content width. It flows onto as many pages as needed.
HTML strings use the same parser as takumi-js. A <style> tag in the string applies only to that render:
import { } from "takumi-pdf";
const = await (`
<style>.total { font-weight: 700 }</style>
<div><span class="total">Total: $1,290</span></div>
`);Headers, footers, and measure() accept the same inputs.
Page setup
import { } from "takumi-pdf";
const = await (, {
: "letter", // "a4", "letter", or { width, height } in CSS px at 96 dpi
: true,
: { : 48, : 32, : 48, : 32 },
});| Option | Type | Default | Description |
|---|---|---|---|
size | "a4", "letter", or { width, height } | "a4" | Page size in CSS px at 96 dpi. Presets ignore case. |
landscape | boolean | false | Swaps page width and height, including explicit sizes. |
margin | number or { top?, right?, bottom?, left? } | 48 | A number applies to all sides. Missing object sides are 0. |
@page CSS rules are not supported. Use these options to set the page geometry.
Reuse a renderer
render() keeps one shared renderer alive. Construct PdfRenderer directly for applications that manage several font sets:
import { } from "takumi-pdf";
const = new ();
await .("https://example.com/Inter-Regular.woff2");
const = await .();Registered fonts deduplicate across calls. Rendering many documents pays the font cost once.
Last updated on