Takumi

From Puppeteer

Migrate Puppeteer PDF templates to takumi-pdf, including page setup, assets, and CSS limitations.

Start with the HTML you pass to page.setContent(). Pass the same string to render(), and translate the page.pdf() options with the option map. Headers and footers use the same pageNumber and totalPages class hooks.

Takumi does not load a page or run its scripts. Generate dynamic content and fetch document images before you render.

Before and after

Before: Puppeteer
// Puppeteer
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setContent(html, { waitUntil: "networkidle0" });

const pdf = await page.pdf({
  format: "A4",
  margin: { top: "48px", bottom: "64px", left: "48px", right: "48px" },
  displayHeaderFooter: true,
  footerTemplate: `<div style="font-size:10px;width:100%;text-align:center">
    Page <span class="pageNumber"></span> of <span class="totalPages"></span>
  </div>`,
  printBackground: true,
});

await browser.close();
After: takumi-pdf
// takumi-pdf
import {  } from "@takumi-rs/helpers";
import {  } from "takumi-pdf";
import { ,  } from "takumi-pdf/primitives";

const  = await (, {
  : "a4",
  : { : 48, : 64, : 48, : 48 },
  : (
    < ="flex w-full justify-center text-[10px]">
      Page < /> of < />
    </>
  ),
  : await (["Inter"]),
});

render() parses HTML strings, including <style> tags. It also takes JSX and node trees, and so do header and footer.

Option map

page.pdf()takumi-pdf
format: "A4"size: "a4"
width, heightsize: { width, height }
landscapelandscape
marginmargin, in CSS px
displayHeaderFooter + headerTemplateheader
footerTemplatefooter
pageNumber, totalPages classesthe same classes
date, title, url classesinterpolate the value yourself
tagged (default on)tagged (default on)
outlineoutline
printBackgroundalways on
pathwrite the returned Uint8Array
timeout, waitForFontsnot needed: no page to load
scalenot supported: scale the CSS instead
pageRangespageRanges: [1, { from: 4, to: 8 }]
preferCSSPageSize, @pagenot supported: set size and margin
omitBackgroundnot supported

Margins take numbers in CSS px, not length strings. For Chromium's "0.5in", pass 48.

Fetching moves to your code

Use prepareImages() to fetch document images before rendering. Parse the HTML first, so the helper can find its image references:

Pass fetched image bytes
import {  } from "@takumi-rs/helpers";
import {  } from "@takumi-rs/helpers/html";
import {  } from "takumi-pdf";

const { ,  } = ();
const  = await ({  });

const  = await (, { ,  }); 

prepareImages() walks the tree and fetches every remote http or https URL in <img src>, background-image, mask-image, and list-style-image. It returns the entries for images.

  • It reads inline styles and tw classes. URLs inside <style> rules are not collected, so pass those images through images yourself.
  • It takes timeout, maxBytes, an allowUrl predicate, and a fetchCache that reuses bytes across renders.

Fonts come from the fonts option, not from CSS @font-face rules. See Fonts & images. Font URL loaders and googleFonts() make their own requests, so give them their own fetch limits.

Check browser-dependent features

Takumi supports a subset of browser CSS. Check these differences before you replace Puppeteer:

  • No scripts. Charts and diagrams have to arrive as markup, SVG, or images. A client-side chart library does not run.
  • Narrower CSS. PDF output rejects filter: blur() and drop-shadow(), and does not draw backdrop-filter. Blurred box-shadow and text-shadow are approximated with bands. Grid, flexbox, transforms, gradients, masks, and clip paths all work.
  • No @page. Page geometry comes from the options.

Keep Puppeteer to reproduce a live web page as a browser shows it. Use takumi-pdf for documents written for print. See Comparison for measured numbers.

Last updated on