You're reading the v2 beta docs. For the stable release, switch to v1 →
TakumiTakumi

Introduction

A Rust engine that renders JSX, HTML, and node trees into images. No headless browser.

Takumi renders JSX, HTML, and node trees into PNG, JPEG, WebP, SVG, and animations. Native Rust on the server, WebAssembly on the edge.

Generate OG images and social cards without a headless browser:

  • No Chromium. Native Rust on the server, WebAssembly on the edge.
  • Drop-in for next/og. ImageResponse matches the API you already ship.
  • Every output from one render. Raster, vector SVG, and animated GIF or WebP.

Install

npm i takumi-js@beta

takumi-js bundles both bindings: the native renderer (@takumi-rs/core) and the WebAssembly one (@takumi-rs/wasm). It picks the right one at runtime — native on Node.js, WebAssembly on Cloudflare Workers, Vercel Edge, Deno, and the browser. No extra install.

Render an image

render takes JSX and returns image bytes. A default sans-serif font is built in, so text works without loading a font.

import { render } from "takumi-js";
import { writeFile } from "node:fs/promises";

const png = await render(
  <div
    style={{
      width: "100%",
      height: "100%",
      display: "flex",
      alignItems: "center",
      justifyContent: "center",
      fontSize: 72,
      background: "linear-gradient(to bottom right, #fff7ed, #fecaca)",
    }}
  >
    Hello Takumi
  </div>,
  { width: 1200, height: 630 },
);

await writeFile("hello.png", png);
  • width and height set the canvas.
  • The root doesn't fill the canvas on its own, so it carries width: 100% and height: 100%.

Serve it over HTTP

ImageResponse extends the web Response, so any runtime with Request and Response can return it. The API matches next/og.

import {  } from "takumi-js/response";

export function () {
  return new (< ={{ : "100%", : "100%" }}>Hello Takumi</>, {
    : 1200,
    : 630,
  });
}

Takumi never reads system fonts. One sans-serif font ships built in (Geist on the native renderer, Manrope on WebAssembly); load every other font through fonts or its glyphs render as tofu. See Fonts.

Coming from satori

The layout defaults differ. A bare <div> is block where satori forces display: flex, and flex-direction defaults to row instead of satori's column. Takumi supports Flexbox, Grid, and block layout where satori is flex-only, and rasterizes directly instead of returning an SVG to convert.

Next steps

Edit on GitHub

Last updated on

On this page