TakumiTakumi

Nitro SSR (TanStack Start)

Integrate Takumi with Nitro-based full-stack frameworks (e.g., TanStack Start) for server-side image generation.

Takumi provides N-API bindings for Node.js and Bun, leveraging Node.js's libuv thread pool for multi-threaded image generation.

Check out the TanStack Start example for a full-functioning example of using Takumi in SSR.

If you are considering using Takumi in any framework or as an endpoint, see the From Next.js ImageResponse guide for usage of the @takumi-rs/image-response package.

Installation

npm i @takumi-rs/core @takumi-rs/helpers

Vite/Nitro (TanStack Start) configuration

When using Vite-based full-stack frameworks built on Nitro (e.g., TanStack Start) with Takumi Core (N-API, not WASM), add the following to your vite.config.ts. This makes sure the native @takumi-rs binaries are traced and not prebundled, and that SSR resolves them at runtime (works great on Vercel with the Nitro preset).

// vite.config.ts
import { defineConfig } from "vite";

export default defineConfig({
  nitro: {
    preset: "vercel",
    externals: {
      traceInclude: [
        "node_modules/@takumi-rs/core",
        "node_modules/@takumi-rs/image-response",
        "node_modules/@takumi-rs/helpers",
        "node_modules/@takumi-rs/core-linux-x64-gnu",
        "node_modules/@takumi-rs/core-linux-arm64-gnu",
        "node_modules/@takumi-rs/core-darwin-arm64",
        "node_modules/@takumi-rs/core-darwin-x64",
      ],
    },
  },
  optimizeDeps: {
    exclude: [
      "@takumi-rs/core",
      "@takumi-rs/image-response",
      "@takumi-rs/helpers",
      "@takumi-rs/core-linux-x64-gnu",
      "@takumi-rs/core-linux-arm64-gnu",
      "@takumi-rs/core-darwin-arm64",
      "@takumi-rs/core-darwin-x64",
    ],
  },
  ssr: {
    external: [
      "@takumi-rs/core",
      "@takumi-rs/image-response",
      "@takumi-rs/helpers",
      "@takumi-rs/core-linux-x64-gnu",
      "@takumi-rs/core-linux-arm64-gnu",
      "@takumi-rs/core-darwin-arm64",
      "@takumi-rs/core-darwin-x64",
    ],
  },
});

With the above in place, usage is the same as Node.js/Bun.

Usage

Initialize a Renderer instance to render images.

import { Renderer } from "@takumi-rs/core";

export const renderer = new Renderer({
  fonts: [/* Add your font buffers */],
  persistentImages: [/* Add your persistent images */]
});

Create a function to construct the layout.
You can also reuse React components via fromJsx.

import { container, text } from "@takumi-rs/helpers";

function createOpenGraphImage(name: string) {
  return container({
    width: 1200,
    height: 630,
    backgroundColor: 0x000000,
    children: [
      text(`Hello, ${name}!`, {
        fontSize: 48,
        color: 0xffffff,
        x: 100,
        y: 100,
      }),
    ],
  });
}

Finally, render the layout to an image buffer.

const imageBuffer = await renderer.render(createOpenGraphImage("John Doe"), {
  width: 1200,
  height: 630,
  format: "webp"
});

Deep dive into advanced usages

If you are interested in more advanced usages of Takumi, take a look at the Deep Dives section.

Edit on GitHub

Last updated on