Open Graph tags in Nuxt
useSeoMeta writes og:title, og:description, og:image, and twitter:card into the head Unhead renders on the server. Call it from the page, with an absolute image URL. Deploy it, then paste that public URL into the checker above.
Add the tags
- useSeoMeta. Nuxt's SEO guide recommends useSeoMeta. The keys are typed, Open Graph keys are written with property, and Twitter keys are written with name, which avoids the mistake of putting og:title on a name attribute. ogTitle becomes og:title. ogDescription becomes og:description. ogImage becomes og:image. ogUrl becomes og:url. ogImageWidth and ogImageHeight become the structured image tags. twitterCard becomes twitter:card. Set it to summary_large_image, or X shows a small thumbnail. The string passed to ogImage is the content attribute, so a path such as /og.png has no host. Use an absolute https URL. A ref or a getter, written () => value, is how the composable docs say to pass a value that changes. Static tags can sit inside if (import.meta.server). That is the pattern Nuxt documents in place of the deprecated useServerSeoMeta, and it runs while the server is rendering the HTML a crawler reads. The How to Add Open Graph Tags page is the properties those keys emit. The Next.js Open Graph page is the same fields as a metadata export.
<script setup lang="ts"> useSeoMeta({ title: "Post title", description: "One or two sentences.", ogTitle: "Post title", ogDescription: "One or two sentences.", ogType: "article", ogUrl: "https://example.com/post", ogImage: "https://example.com/og.png", ogImageWidth: 1200, ogImageHeight: 630, ogImageAlt: "What the image shows", twitterCard: "summary_large_image", twitterImage: "https://example.com/og.png", }) </script> - useHead, and the title template. useHead is the lower-level composable. A meta entry with property is an Open Graph tag. A meta entry with name is the description or a Twitter tag. Nuxt also ships Head, Title, and Meta components. The docs say to wrap them in Head so deduping stays predictable, and a Meta nested inside Head is still rendered in the document head. definePageMeta is extracted at build time. The SEO guide says it cannot be set from a value you compute at runtime. The pattern they show is a static title on the page, read back as route.meta.title from a layout. A title that comes from a fetched post belongs in useSeoMeta or useHead after that data exists. app.head in nuxt.config.ts is the static default for the whole app. It is not reactive. A titleTemplate in app.vue rewrites the document title, including a %s placeholder. It leaves og:title alone, so set ogTitle to the string the card should show. Unhead keeps one tag for a given property or name, so the page's og:title replaces the layout's.
useHead({ meta: [ { property: "og:title", content: "Post title" }, { property: "og:description", content: "One or two sentences." }, { property: "og:url", content: "https://example.com/post" }, { property: "og:image", content: "https://example.com/og.png" }, { name: "twitter:card", content: "summary_large_image" }, { name: "twitter:image", content: "https://example.com/og.png" }, ], link: [{ rel: "canonical", href: "https://example.com/post" }], }) - The first HTML response. Unhead renders these tags during server-side rendering, so they are in the first HTML response. SSR is Nuxt's default. ssr: false in nuxt.config turns the app into a client-rendered shell. The composable then runs in the browser, and a crawler that does not execute JavaScript receives a head without the page's og: tags. The useSeoMeta docs say robots primarily scan that initial page load, which is why static tags belong in the server render. Tags set inside onMounted have the same hole. View source, or curl the URL, and read the head. The Open Graph protocol gives the first tag preference when two of the same property are present, and this checker reads the first og:title, og:description, and og:image. One tag in the HTML is the result you want. Set twitterImage when the X image should differ from og:image. X falls back to og:image for the file, and twitter:card is what selects the large layout. The X (Twitter) Link Preview page is that fallback.
- Check the public URL. Paste the public URL, not a localhost address. Peekly grades og:title, og:description, og:image, and twitter:card from the HTML your server sends, and it downloads the image. A title that is only the site name is a titleTemplate whose page title was empty, or an ogTitle that was never set. An image URL that starts with a slash is the relative path the composable was given. The Open Graph Checker is that grade. The Twitter Card Validator is the card twitterCard selects. The Astro Open Graph, Remix Open Graph, and SvelteKit Open Graph pages are the same tags in those frameworks. The Open Graph Image Size page is the 1200×630 file those width and height values should describe.
Tags covered: og:title · og:description · og:image · og:url · og:type · twitter:card · twitter:image
More checkers
Twitter Card ValidatorOpen Graph CheckerLinkedIn Link Preview CheckerDiscord Embed PreviewWhatsApp Link Preview CheckerSlack Link Preview CheckeriMessage Link Preview CheckerFacebook Link Preview CheckerOpen Graph Image SizeTelegram Link Preview CheckerReddit Link Preview CheckerNext.js Open GraphRefresh a Link Preview CacheBluesky Link Preview CheckerMastodon Link Preview CheckerMicrosoft Teams Link Preview CheckerFix a Broken Open Graph PreviewInstagram Link Preview CheckerPinterest Link Preview CheckerTikTok Link Preview CheckerYouTube Link Preview CheckerThreads Link Preview CheckerSnapchat Link Preview CheckerHow to Add Open Graph TagsOpen Graph Image Not UpdatingDiscord Link PreviewX (Twitter) Link PreviewWordPress Open GraphShopify Open GraphAstro Open GraphRemix Open GraphSvelteKit Open GraphAll platforms
What each platform reads
- X / Twittertwitter:card, twitter:* → og:* fallback1200×630 (min 300×157), < 5 MB
- Facebookog:title, og:description, og:image1200×630, 1.91:1
- LinkedInog:title, og:image (og: only)1200×627, 1.91:1
- Discordog:site_name, og:*, theme-color, twitter:cardLarge image needs summary_large_image
- Slackog:site_name, og:title, og:description, og:image1200×630
- WhatsAppog:title, og:description, og:imageKeep < 300 KB
Guidance based on each platform's public documentation and observed behavior. Platforms change their rules without notice.
FAQ
+Is Peekly free?
Yes. Checking a single URL is free forever — no signup and no limit on one-off checks. Batch watching and monitoring may arrive later as a paid Pro plan; the free single-URL tool stays.
+Why does my link show no image when I share it?
Usually one of four things: there's no og:image tag, the image URL is relative instead of absolute, the image is behind a login, firewall or bot block, or the file is too big or in an unsupported format like SVG. Peekly checks all four and tells you which one it is.
+What size should my og:image be?
1200×630 pixels (a 1.91:1 ratio) as a PNG or JPG under about 300 KB. That size works for large cards on X, Facebook, LinkedIn, Discord, Slack and WhatsApp.
+Do I need twitter: tags if I already have Open Graph tags?
X reads og:title, og:description and og:image as fallbacks, but you still need twitter:card set to summary_large_image if you want the big image card. Without it, X shows a small thumbnail.
+I fixed my tags but the old preview still shows. Why?
Platforms cache link previews, sometimes for days. Facebook and LinkedIn let you force a refresh with their own debugging tools. On X, Slack and Discord the cache usually expires on its own, or you can add a query string such as ?v=2 to the URL.
+Do you store the pages I check?
No. We fetch the page once to read its <head>, show you the result, and don't save the page or the result. We only fetch public http(s) URLs, and private or internal addresses are blocked.
+Are the previews pixel-perfect?
They're close approximations of each platform's current card layout, built from the same tags the platforms read. Platforms change their designs from time to time, so treat them as a very good guide rather than a screenshot.
$9
One time
A written fix for the batch.
Up to 25 URLs. We check og:image, Twitter cards, size, redirects, and cache, then send copy-paste meta tags within 48 hours. The free single-URL check stays free.