TakumiTakumi

Use Takumi in Cloudflare Workers

Integrate Takumi with Cloudflare Workers image generation at the edge.

Takumi has first-class support for Cloudflare Workers, allowing you to generate images dynamically at the edge without any cost.

Thanks to awesome performance optimizations, Takumi works within Workers' free plan CPU time constraints. Here's a deployed example: takumi-on-workers-example.kane.tw?name=your-name.

Create a New Wrangler Project

First, create a new Cloudflare Workers project using Wrangler:

npm create cloudflare@latest og-image-worker

Navigate to your project directory:

cd og-image-worker

Install Dependencies

Install Takumi packages and Wrangler:

npm install @takumi-rs/wasm @takumi-rs/helpers

Configure Wrangler

If you are using external fonts or images, add rules configuration to your wrangler.jsonc to handle import statements.

The verified minimum compatibility date is 2025-08-03. If you are encountering errors related to WASM module initialization, please check your compatibility date.

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "og-image-worker",
  "main": "src/index.ts",
  "compatibility_date": "2025-08-03",
  "rules": [
    {
      "type": "Data",
      "globs": ["**/*.ttf", "**/*.woff", "**/*.woff2"],
      "fallthrough": true
    }
  ]
}

Initialize WASM Module

Import the WASM like this and Wrangler will handle the initialization part for you. Make sure to call initSync before initializing the Renderer instance.

import { initSync, Renderer } from "@takumi-rs/wasm";
import module from "@takumi-rs/wasm/takumi_wasm_bg.wasm";

initSync({ module });

const renderer = new Renderer();

Load Static Assets

To maintain the minimal size of the WASM file, we don't provide default embedded fonts like Geist or Geist Mono. You need to load them manually.

Load fonts and persistent images when your worker starts.

import { initSync, Renderer } from "@takumi-rs/wasm";
import module from "@takumi-rs/wasm/takumi_wasm_bg.wasm";
import medium from "../../assets/fonts/noto-sans/noto-sans-v39-latin-500.woff2";
import bold from "../../assets/fonts/noto-sans/noto-sans-v39-latin-700.woff2";

initSync({ module });

const renderer = new Renderer();

renderer.loadFont(new Uint8Array(medium));
renderer.loadFontWithInfo({
  data: new Uint8Array(bold),
  name: "Noto Sans",
  weight: 700,
  style: "normal",
});

Handle Dynamic Assets

Cloudflare Workers does not support top-level await, so you need to initialize assets in the fetch handler.

// Store in base64 data URI
let logoUrl: string;

export default {
  async fetch(request: Request) {
    logoUrl ??= await fetchLogo();
  },
}

Deploy

Deploy your worker using Wrangler:

npm run deploy

You should now have a working Takumi worker. Check out the full Cloudflare Workers example here to see a working example.

If you encounter any issues, please file an issue here.