Skip to main content

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.ts Vercel Edge Function re-exporting buildOgResponse, dynamic per-page titles via query params.
  • Astro sites (org, docs, tv): a static public/og.png rendered from the same shared template. @vercel/og only runs on the Edge runtime, and the Astro Vercel adapter deploys endpoints as Node serverless functions (root api/ directories are not deployed for Build Output API frameworks), so a dynamic /api/og route 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
nself.org/docs 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. nself.org/docs / 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.