Open Graph and Twitter Cards that render
Open Graph is the easiest piece of SEO metadata to get half-right. The hard part is shipping a card that survives every social platform without falling back to a default placeholder. This is the practical playbook.
The minimum tags that work
Eleven tags. Anything less and at least one platform breaks.
<title>Your page title (under 60 chars)</title>
<meta name="description" content="Your description, ideally 150-160 chars." />
<link rel="canonical" href="https://yourdomain.com/page" />
<meta property="og:type" content="website" />
<meta property="og:title" content="Your page title" />
<meta property="og:description" content="Your description" />
<meta property="og:url" content="https://yourdomain.com/page" />
<meta property="og:image" content="https://yourdomain.com/page/og.png" />
<meta property="og:site_name" content="Your Site" />
<meta property="og:locale" content="en_US" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Your page title" />
<meta name="twitter:description" content="Your description" />
<meta name="twitter:image" content="https://yourdomain.com/page/og.png" />
<meta name="twitter:site" content="@yoursite" />Build the block interactively with the Meta Tag Generator.
Image rules that get violated all the time
Most "the image isn't showing" tickets trace to one of these.
Use 1200x630
This is the universally supported size. 1.91:1 aspect ratio. Some platforms downscale, none of them upscale gracefully.
Stay under 5 MB
Some platforms cache only the first 5 MB of the URL. PNGs at this size should easily fit; if yours doesn't, your image is too detailed for a 200x100-display preview.
The URL must be absolute and HTTPS
Relative URLs and http:// URLs fail silently on some platforms. Always:
<meta property="og:image" content="https://yourdomain.com/og.png" />Not /og.png. Not //yourdomain.com/og.png.
The URL must return HTTP 200 publicly
A common failure: the image is behind a CDN that requires a signed URL or a logged-in session. Social crawlers fetch unauthenticated. Test with a fresh incognito window or curl from a different network.
The URL must not redirect
Some crawlers follow redirects, some don't. Skip the question and serve the final image at its canonical URL.
og:url has to match canonical
If og:url and <link rel="canonical"> disagree, AI agents and SEO crawlers flag it. The two should always be identical and absolute. SEO audits will demote pages that get this wrong.
og:locale and og:site_name matter
Two fields that get dropped because the layout-level metadata gets shallow-merged away by the page-level override. In Next.js, this is the most common Open Graph bug.
When a page sets openGraph: { title, description }, the layout's siteName, locale, and other fields are dropped. Always include them in every page's openGraph block:
export const metadata: Metadata = {
title: "About",
description: "About our company.",
openGraph: {
title: "About | Your Site",
description: "About our company.",
url: "https://yourdomain.com/about",
type: "website",
siteName: "Your Site",
locale: "en_US",
},
};If you only set title and description in openGraph, expect SEO crawlers to flag the missing fields.
Per-page OG images via file convention
Next.js 16 supports placing opengraph-image.tsx in any route segment. The framework auto-injects og:image, og:image:type, og:image:width, and og:image:height for that segment.
// app/blog/[slug]/opengraph-image.tsx
import { ImageResponse } from "next/og";
export const size = { width: 1200, height: 630 };
export const contentType = "image/png";
export default async function Image({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
return new ImageResponse(
<div style={{ display: "flex" /* ... */ }}>{/* your composition */}</div>,
size
);
}Pair with twitter-image.tsx to set twitter:image similarly. Most teams export both from the same source.
This pattern eliminates the per-page asset management that traditionally breaks at scale.
Twitter card types
Two of the four Twitter card types matter.
summary— small square thumbnail. Use for utility pages where the image is a logo.summary_large_image— full-width hero. Use for blog posts and marketing pages. This is the modern default.
The other two (app, player) exist for app cards and video and rarely apply to content sites.
Validation
After you deploy, validate with three tools.
- Meta Sharing Debugger — Facebook, Instagram, WhatsApp.
- X Card Validator — at
cards-dev.twitter.com/validator. Login required as of mid-2025. - LinkedIn Post Inspector — refresh LinkedIn's preview cache for a URL.
For Open Graph beyond just social, also run the page through Google's Rich Results Test since it surfaces JSON-LD issues that compound with OG bugs.
When the preview is stale
Social platforms cache aggressively. After publishing changes, you usually need to force a refresh:
- Facebook / Meta: paste the URL into the Sharing Debugger and click "Scrape Again".
- LinkedIn: paste into the Post Inspector. Refresh runs once per URL.
- X: re-validate in the card validator. Some changes take 30 minutes to propagate.
- Slack: there is no UI. The cache invalidates after ~24 hours, or you can prepend a fragment (
#v=2) to force a fresh fetch.
Common mistakes summary
- Using a relative
og:imageURL. - Setting only some Open Graph fields and losing layout-level fields to shallow merge.
- Forgetting
og:urlor having it disagree with the canonical. - Image URL that requires auth or sits behind a redirect.
- Image larger than 5 MB or too small to render at 1200x630.
og:typeset to something exotic whenwebsiteorarticleis what you actually mean.
What we ship at AgentScan
Every page on this site has its own opengraph-image.tsx plus a twitter-image.tsx that re-exports from it. The image renders the page title and description on a per-section gradient. The metadata block on each page sets siteName, locale, type, url, title, and description so nothing is lost to shallow merge.
If your site does not yet do this, the work is two hours and the cards become substantially more clickable. Build the tags with the Meta Tag Generator and the OG images with next/og's ImageResponse API.