OG / Social Cards
How to add Open Graph metadata to new pages across ɳSelf web properties.
Every ɳSelf web property generates dynamic Open Graph (OG) images via the shared
nself package. Cards render correctly on Twitter/X, LinkedIn, Slack unfurl,
and Facebook.
Architecture
The shared package at web/packages/og/ provides:
colors.ts: product accent color map (7 products)template.tsx: Satori JSX template (1200×630, gray-950 background, left accent bar)route.ts: Edge Function handler with 24h cache headers
How each app serves OG images depends on its framework:
- Vite SPAs (task, sentry): a root-level
api/og.tsVercel Edge Function re-exportingbuildOgResponse— dynamic per-page titles via query params. - Astro sites (org, docs, tv): a static
public/og.pngrendered from the same shared template.@vercel/ogonly runs on the Edge runtime, and the Astro Vercel adapter deploys endpoints as Node serverless functions (rootapi/directories are not deployed for Build Output API frameworks), so a dynamic/api/ogroute is not possible there.
Adding OG metadata to a new page
In any page.tsx or layout.tsx:
export const metadata = {
openGraph: {
images: [{
url: `/api/og?title=${encodeURIComponent('Your Page Title')}&product=docs`,
width: 1200,
height: 630,
}],
},
twitter: {
card: 'summary_large_image',
images: [`/api/og?title=${encodeURIComponent('Your Page Title')}&product=docs`],
},
}
Replace product=docs with the product key for the app you are working in.
Product keys
| App | Key |
|---|---|
| nself.org | org |
| docs.nself.org | docs |
| cloud.nself.org | cloud |
| chat.nself.org | nself |
| claw.nself.org | nself |
| ntv.nself.org | nself |
| family.nself.org | nself |
| task.nself.org | nself |
| clawde.nself.org | clawde |
Query parameters
| Param | Required | Description |
|---|---|---|
title | Yes | Page title, displayed at 56px bold, truncated at 80 chars |
product | No | Product key (defaults to org) |
breadcrumb | No | Subtitle below title, e.g. docs.nself.org / guides / deploy |
Fallback
If the /api/og route is unreachable, the browser falls back to the static
/og-default.png (1200×630) in each app’s public/ directory. Keep this file
up to date with the current brand.
Cache
All /api/og responses carry:
Cache-Control: public, max-age=86400, s-maxage=86400
Vercel caches at the edge. Cold start renders in well under 500ms.