ImageResponse
Return rendered images from HTTP route handlers with the next/og-compatible ImageResponse API.
Return an ImageResponse from a route handler to serve a rendered image. It extends the web Response, so it works in any runtime with Request and Response. Its API matches next/og.
import { } from "takumi-js/response";
export function () {
return new (<>Hello Takumi</>, { : 1200, : 630 });
}The first argument takes what render() takes: JSX, an HTML string, or a node tree.
Options
ImageResponseOptions is the render() options plus the ResponseInit fields and an error hook.
Prop
Type
Description
width?numberImage width in pixels. Omit it to size the width to the content.
height?numberImage height in pixels. Omit it to size the height to the content.
quality?numberEncoder quality, 0–100. Applies to JPEG and lossy WebP.
fonts?FontLoader[] | Promise<FontLoader[]>Fonts for this response. Each file decodes once per renderer.
images?ImageLoader[] | { sources, fetchCache, cache, ...fetchOptions }Pre-fetched images keyed by src, and limits for the images Takumi fetches.
emoji?"twemoji" | "blobmoji" | "noto" | "openmoji" | "fluent" | "fluentFlat" | "from-font"Where emoji glyphs come from.
jsx?FromJsxOptionsJSX conversion options, such as { defaultStyles: false }.
headers?HeadersInitResponse headers. content-type defaults to match format.
status?numberResponse status code.
statusText?stringResponse status text.
onError?(error: unknown) => void | Promise<void>Runs after a render fails. Defaults to logging the error with console.error.
Custom headers
content-type follows format unless you set it. Takumi sets no other headers. This handler lets browsers and shared caches reuse the image for one hour:
import { } from "takumi-js/response";
export function () {
return new (<>Hello Takumi</>, {
: 1200,
: 630,
: "webp",
: {
"Cache-Control": "public, max-age=3600",
},
});
}Match max-age to how often the content changes.
Error handling
The response streams its body while the render runs, so the status is already set when a render fails. To send a fallback instead, await ready. It resolves when the render succeeds and rejects when it fails.
import { } from "takumi-js/response";
export async function () {
const = new (<>Hello Takumi</>, { : 1200, : 630 });
try {
await .;
return ;
} catch {
return new ("Failed to generate image", { : 500 });
}
}onError is for side effects such as logging. Takumi ignores its return value, and the response stream still errors. Use ready to send a fallback.
import { } from "takumi-js/response";
export function () {
return new (<>Hello Takumi</>, {
: 1200,
: 630,
: () => .(),
});
}Bring your own renderer
Without renderer, every response in the process shares one default renderer and its caches. Pass your own Renderer to configure it: set cache budgets, or register fonts up front.
import { } from "takumi-js/node";
import { } from "takumi-js/response";
const = new ({ : 128 * 1024 * 1024 });
export function () {
return new (<>Hello Takumi</>, {
: 1200,
: 630,
,
});
}takumi-js/node exports the native renderer. On WebAssembly runtimes, use the Renderer from takumi-js/wasm and call its init first, as in the measure() example.
Last updated on