How Takumi works
Learn how Takumi turns JSX, HTML, and CSS into images, PDFs, or paint trees, and where it behaves differently from a browser.
Takumi is one Rust engine. Its text and inline layout port Chromium's Blink, and the same layout feeds three packages.
- boxdiv
- boxdiv
- boxdiv
- boxb
- text"Hello, paint"
- boxspan
- text"Boxes, text, and steps"
From input to output
Input
A render starts with JSX, an HTML string, or a node tree. Every node in a tree is a container, text, or image. A node tree holds content and style only, so fonts, images, and output options are separate arguments to render. Parsing templates covers the input forms.
Styles
Styles come from the style prop, a stylesheet, or Tailwind utilities. A stylesheet reaches Takumi through css or a <style> tag, and the tw prop runs a built-in Tailwind parser that needs no build step. The style prop beats the tag default and every matching stylesheet rule of the same importance. Styles says which declaration wins.
Layout and output
Layout covers Flexbox, Grid, block, float, tables, and inline layout from Blink. The same layout produces every output:
| Package | Output |
|---|---|
takumi-js | PNG, JPEG, WebP, ICO, raw pixels, SVG, and animated WebP, APNG, or GIF |
takumi-pdf | Paged PDF with selectable text |
takumi-paint | A paint tree to draw with Canvas, slides, or a native API |
Where it differs from a browser
Fonts
Takumi never reads system fonts, and its one built-in font is Geist, which covers Latin at weights 300 to 800. Load a font for every script your text uses. See Fonts.
One static frame
Interactive pseudo-classes such as :hover and :focus parse but never match. In @media, image renders are screen and PDF renders are print. Any feature the media query table does not list matches nothing, prefers-color-scheme included. See Styles.
Tailwind and rem
The built-in parser applies no Tailwind Preflight by default, so elements keep their default margins. In a tree without an <html> root, rem resolves against the viewport's font size, which is 16px. A full HTML document passed to fromHtml keeps its <html> element, so a font size there sets the rem basis. See Styles and the reference.
Strict style objects
A property name outside the supported list is dropped without an error. A listed name with an unparsable value fails the whole style object. Only writing-mode: horizontal-tb is laid out. See the reference.
Tables
Tables follow Chromium's table layout, with a few cases that drift, such as how a row baseline is measured and where page breaks fall. See Tables.
Remote images
Remote images load only from an <img> src and from background-image, mask-image, and list-style-image in a node's style or tw. Takumi does not fetch URLs inside css or a <style> tag, so pass those images as pre-fetched images. See Image loading & emoji.
PDF filters
A PDF cannot draw filter: blur() or drop-shadow(). The renderer stops rather than ship a page that differs from the image output. See Troubleshooting.
Coming from satori
The migration guide lists the differences between satori or next/og and Takumi.
Last updated on