Nitro
Render OG images from a Nitro server route.
Install Takumi
npm i takumi-jsCreate a server route
Build the node tree with helpers, so no JSX setup is needed. Nitro handlers can return a Response, so return an ImageResponse directly.
import { defineHandler } from "nitro";
import { container, text } from "takumi-js/helpers";
import ImageResponse from "takumi-js/response";
export default defineHandler((event) => {
const url = new URL(event.req.url);
const title = url.searchParams.get("title") ?? "Takumi + Nitro";
const description =
url.searchParams.get("description") ?? "Render OG images from a Nitro route.";
return new ImageResponse(
container({
style: {
width: "100%",
height: "100%",
display: "flex",
flexDirection: "column",
justifyContent: "center",
padding: "64px",
backgroundImage: "linear-gradient(to bottom right, #fff1f2, #fecdd3)",
},
children: [
text(title, { fontSize: 72, fontWeight: 700, color: "#111827" }),
text(description, { fontSize: 42, fontWeight: 500, color: "#4b5563" }),
],
}),
{
width: 1200,
height: 630,
},
);
});Request the endpoint
Visit /og.png?title=Hello&description=From%20Nitro.
Every Nitro preset renders on the WebAssembly backend. Nitro sets the unwasm export condition while wasm is on (the default), so the WASM binary ships inside your server bundle. Nothing has to resolve a native addon at runtime, so the same route deploys to an edge preset and runs in a WebContainer (StackBlitz, CodeSandbox).
Prefer the faster native bindings on the Node preset? Drop the condition:
export default defineNitroConfig({
exportConditions: ["!unwasm"],
});wasm: false gets you the native bindings too, but it also unplugs unwasm from the build, so .wasm imports elsewhere in your app stop resolving. Negating the condition leaves the plugin in place.
Last updated on