OG templatesPro
Open graph image templates for docs pages, models and changelogs, rendered with Satori, in light and dark.
On this page
ProDocs, model and changelog cards, previewed from the same JSX Satori renders to PNG, in light and dark.
Installation
The in-page preview is its own item:
Usage
import { readFile } from "node:fs/promises"
import { ImageResponse } from "next/og"
import { OG_SIZE, OgDocs } from "@/components/ui/chatcn/pro/og-templates"
export const size = OG_SIZE
export const contentType = "image/png"
export default async function Image({ params }) {
const page = await getPage((await params).slug)
const font = (w) => readFile(`node_modules/geist/dist/fonts/geist-sans/Geist-${w}.ttf`)
return new ImageResponse(
<OgDocs title={page.title} description={page.description} section={["Components"]} url={`yoursite.dev/docs/${page.slug}`} />,
{
...OG_SIZE,
fonts: [
{ name: "Geist", data: await font("Regular"), weight: 400 },
{ name: "Geist", data: await font("Medium"), weight: 500 },
{ name: "Geist", data: await font("SemiBold"), weight: 600 },
],
},
)
}The templates are plain functions that return JSX written for Satori: inline styles, flex layout, no CSS variables. They have no client code, so a server route can call them. Colors are the kit's OKLCH tokens converted to sRGB, since Satori cannot read the theme. Long text is trimmed to whole words by a character budget, so a long title never overflows the card.
OgTemplatePreview shows the same JSX in your page, laid out at 1200 x 630 and scaled, so what you see in the docs is what the PNG will be.
Examples
Long content
ProTitles, descriptions and changes trimmed to whole words, so the PNG and the preview cut at the same word.
Props
Shared
| Prop | Type | Notes |
|---|---|---|
theme | "light" | "dark" | Default light |
brand | ReactNode | Your mark and name, top left. Satori safe |
url | string | A short URL, bottom left, in mono |
fontFamily / monoFamily | string | The names you load fonts with. Default Geist and Geist Mono |
OgDocs
| Prop | Type | Notes |
|---|---|---|
title | string | Up to two lines |
description | string | Up to three lines |
section | string[] | Where the page sits |
badge | string | A short label, bottom right |
OgModel
| Prop | Type | Notes |
|---|---|---|
name | string | The model |
maker | string | Who makes it |
specs | { label, value, unit? }[] | Up to four, in a ruled row with tabular figures |
modalities | string[] | Up to four pills, bottom right |
OgChangelog
| Prop | Type | Notes |
|---|---|---|
version | string | Large, on the start side |
date | Date | string | Dates format as 29 Oct 2026 |
changes | { kind: "added" | "improved" | "fixed" | "removed", text }[] | Up to four, one line each |
more | number | How many more changes the release has |
OgTemplatePreview
| Prop | Type | Notes |
|---|---|---|
children | ReactNode | A template element |
alt | string | What the image says. Start with the title it shows |
width | number | Displayed width in px. Default 600 |
Keyboard
None. The preview is a picture.
Accessibility
- The preview is one image with your
alttext; the template inside is hidden from assistive technology. - Change kinds keep their word as the badge text, so the meaning never rests on color alone.
Motion
- None. The cards are still images.