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

SvelteKit

Use Takumi to render your Svelte components on the server.

Install Takumi

npm i takumi-js@beta

Make a Svelte component

Set css="injected" so the <style> block is inlined into the SSR HTML.

src/lib/components/OgImage.svelte
<script lang="ts">
  let { name = "Goo goo gaga" } = $props();
</script>

<svelte:options css="injected" />

<div
  id="og-image"
  class="w-full h-full flex items-center justify-center p-12 flex-col gap-4"
>
  <div class="text-center whitespace-pre-wrap leading-normal text-7xl font-semibold text-black">
    Welcome {name} to
    <span class="font-bold">Svelte</span> world
  </div>
</div>

<style>
  #og-image {
    background-image: linear-gradient(to bottom right, var(--color-orange-50), var(--color-red-200));
  }
</style>

Render the component on a server route

  • Import the component, and app.css if you use Tailwind.
  • Render to HTML with render from svelte/server.
  • Return an ImageResponse.
src/routes/+server.ts
import { render } from "svelte/server";
import style from "../app.css?inline";
import ImageResponse from "takumi-js/response";
import OgImage from "$lib/components/OgImage.svelte";
import type { RequestEvent } from "./$types";

export async function GET({ url }: RequestEvent) {
  const { body, head } = await render(OgImage, {
    props: {
      name: url.searchParams.get("name") ?? "Goo goo gaga",
    },
  });

  return new ImageResponse(`${head}${body}`, {
    width: 1200,
    height: 630,
    stylesheets: [style],
    fonts: [
      {
        name: "Geist",
        data: () =>
          fetch("https://takumi.kane.tw/fonts/Geist.woff2").then((res) => res.arrayBuffer()),
      },
    ],
  });
}
Edit on GitHub

Last updated on

On this page