---
title: "Open Graph Images"
slug: "og-images"
category: "seo"
tags: ["seo", "open-graph", "social"]
status: "stable"
last_updated: 2026-05-14
summary: "Sizing, per-page generation, template design, and debugging for og:image and twitter:image."
related: ["[[seo/technical]]", "[[seo/structured-data]]", "[[seo/image-seo]]", "[[frontend/nextjs]]", "[[seo/glossary]]", "[[seo/audit-checklist]]"]
---

## Overview

The Open Graph image is the unit of social distribution. Slack, Discord, X, LinkedIn, iMessage, and most LLM chat surfaces render the OG image when a URL is pasted. A page without a tuned OG image is invisible in feeds and unshareable in practice. Generate one per page, not one per site.

## Ship 1200x630, keep aspect at 2:1, never below 600x315

The default Open Graph image is 1200 by 630 pixels. Most platforms downscale; few upscale.

- Default: 1200x630 (2:1).
- Minimum: 600x315. Anything smaller renders as a thumbnail or gets dropped.
- Maximum file size: 8 MB per the spec, but keep under 1 MB to avoid platform-level skips.
- Format: PNG for type, JPG for photography, WebP only as a secondary asset (some scrapers still miss it).

Declare dimensions and type so the scraper does not have to fetch the file to measure it:

```html
<meta property="og:image" content="https://example.com/og/seo-technical.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="Technical SEO. The pre-publish checklist." />
<meta name="twitter:card" content="summary_large_image" />
```

## Generate one image per page, not one for the whole site

A single sitewide OG image collapses every share into a brand placeholder. Per-page generation lifts CTR in feeds by a measurable amount.

- Next.js: use the App Router `opengraph-image.tsx` convention or `generateImageMetadata` for per-route variants. See [[frontend/nextjs-metadata-api]].
- Anywhere on Vercel: `@vercel/og` renders JSX to PNG at the edge.
- Framework-agnostic: Satori renders JSX to SVG; pair with `resvg` to rasterize.
- Static sites: pre-generate at build time and write to `public/og/<slug>.png`.

Drive each image from the page's frontmatter (`title`, `summary`, `category`) so the image cannot drift from the page. The on-page image rules in [[seo/image-seo]] still apply: fixed dimensions, alt text, and an absolute URL.

## Design the template for one-glance readability

The image is rendered at 200 pixels wide on a phone home screen. Treat that as the design target, not 1200.

- Title at 60 to 80 pixels tall, two lines maximum, ellipsize beyond that.
- One-line context underneath: category, date, or domain.
- Brand mark in a corner; do not center it.
- Contrast ratio of at least 7:1 between text and background.
- No decorative imagery behind the title unless it darkens to 30% opacity.
- One typeface, two weights. Three weights starts to look like a slide deck.

Match the visual system to the canonical site brand so a card in a feed reads as your domain at a glance.

## Use absolute URLs in `og:image`

Scrapers fetch the meta tag in isolation; a relative path resolves against the scraper's origin, which is wrong. Always:

```html
<meta property="og:image" content="https://example.com/og/seo-technical.png" />
```

Pair the absolute URL with the canonical declared on the same page (see [[seo/technical]]). The canonical and the `og:url` must match, or some platforms strip the card.

## Bust the cache on every regeneration

Facebook, X, LinkedIn, and Slack each cache OG metadata aggressively. A regenerated image at the same URL will not surface until the cache expires (days to weeks).

- Append a content hash to the filename or query string: `og/seo-technical.png?v=8f3a`.
- Update the `og:image` URL in the HTML on the same deploy.
- Re-scrape proactively in the Facebook Sharing Debugger, the X Card validator, and the LinkedIn Post Inspector.

Plan for a one-cycle delay on platforms that have no manual refresh.

## Debug with the platform validators, in this order

Different platforms parse different subsets of the spec. Validate against all three before declaring a card "done."

- Meta Sharing Debugger (`https://developers.facebook.com/tools/debug/`).
- X Card Validator (`https://cards-dev.x.com/validator`).
- LinkedIn Post Inspector (`https://www.linkedin.com/post-inspector/`).

If the image renders correctly on these three, Slack, Discord, and iMessage will follow.

## Related

- [[seo/technical]]
- [[seo/structured-data]]
- [[frontend/nextjs]]
- [[frontend/html]]
- [[seo/glossary]]
- [[seo/audit-checklist]]
