Guides creation of OpenGraph and Twitter share images using next/og ImageResponse. Covers layout patterns, custom fonts, avatars, title case, and Satori rules. Use when building OG images, Twitter cards, or social previews.
View on GitHubFebruary 1, 2026
Select agents to install to:
npx add-skill https://github.com/richtabor/agent-skills/blob/main/skills/og-images/SKILL.md -a claude-code --skill og-imagesInstallation paths:
.claude/skills/og-images/# Creating Share Images for Next.js
Generate dynamic OpenGraph (1200x630) and Twitter (1200x600) images using `next/og` ImageResponse.
## Choosing an Approach
- **File-based route** (`app/opengraph-image.tsx`): Best for static pages with known titles at build time. Export `runtime`, `alt`, `size`, `contentType`, and a default `Image` function.
- **API route** (`app/api/og/route.tsx`): Best for dynamic content (blog posts, CMS). Accept `slug` and/or `title` as query params. Reference in metadata via `generateMetadata()`.
Use `export const runtime = "edge"` for both approaches.
## File Naming Convention
| File | Purpose | Dimensions |
|------|---------|------------|
| `opengraph-image.tsx` | Facebook, LinkedIn, iMessage | 1200x630 |
| `twitter-image.tsx` | Twitter/X cards | 1200x600 |
| `app/api/og/route.tsx` | Dynamic API route | 1200x630 |
Place file-based routes in the relevant route directory (e.g., `app/about/opengraph-image.tsx` for `/about`).
## Layout Pattern
- Use `flexDirection: "column"` with `justifyContent: "space-between"` to separate content from branding
- Title and subtitle (e.g., author name) go top-left in a stacked flex column
- Title: large, bold/medium weight, dark color
- Subtitle: same size or smaller, lighter weight, muted color (e.g., `#888`)
- Keep text left-aligned with `textWrap: "balance"` and constrain width with `maxWidth`
- Use `letterSpacing: "-0.02em"` for tight, editorial feel at large sizes
- Padding: `48px` on all sides works well at 1200x630
## Avatar / Logo (Optional)
If the project has an avatar or logo, place it in the bottom-right corner using a flex container with `justifyContent: "flex-end"`. Load images via `fetch` + `arrayBuffer`, convert to base64 data URI for the `src`. Use `borderRadius: "50%"` for circular avatars. Cache loaded assets in a `Map` to avoid refetching.
## Custom Fonts
Load `.ttf` files from `public/fonts/` using `new URL("../../../public/fonts/YourFont.ttf", import.meta.url)`. Pass the `Arra