twitterCard is required. no fallback from OG tags for card typesummary_large_image for full-width previews (1200x630px recommended)Twitter ignores most Open Graph tags and requires its own twitter:* meta tags for rich link previews. Without them, your links appear as plain text with no image or description.
<script setup lang="ts">
useSeoMeta({
twitterCard: 'summary_large_image',
twitterImage: '/social-preview.jpg',
twitterTitle: 'Your page title',
twitterDescription: 'Your page description'
})
</script>
Twitter supports four card types via twitter:card:
summary_large_image - Full-width image preview (1200x630px). Use this for most pages.
useSeoMeta({
twitterCard: 'summary_large_image',
twitterImage: '/preview.jpg' // Minimum 300x157px, aspect ratio 2:1
})
summary - Small square thumbnail (1:1 aspect ratio). Don't use this unless you specifically want a smaller preview.
useSeoMeta({
twitterCard: 'summary',
twitterImage: '/icon.jpg' // Minimum 144x144px
})
player - Embedded video/audio player. Requires approval from Twitter.
app - Mobile app install prompts. Requires app store URLs and IDs.
Most sites should only use summary_large_image.
These three tags are mandatory for any Twitter Card:
useSeoMeta({
twitterCard: 'summary_large_image',
twitterTitle: 'Page title - 70 characters max',
twitterImage: 'https://example.com/image.jpg' // Must be absolute URL
})
Image requirements:
summary_large_image: 2:1 ratio (1200x630px recommended)summary: 1:1 ratio (300x300px minimum)useSeoMeta({
twitterCard: 'summary_large_image',
twitterTitle: 'Your title',
twitterImage: '/preview.jpg',
twitterDescription: 'Description text - 200 characters max',
twitterSite: '@yourhandle', // Your site's Twitter handle
twitterCreator: '@authorhandle' // Content author's handle
})
twitterDescription defaults to og:description if not set, but specify it to control the exact text Twitter shows.
Twitter falls back to Open Graph tags when twitter:* tags are missing:
| Twitter Tag | Fallback |
|---|---|
twitter:title | og:title |
twitter:description | og:description |
twitter:image | og:image |
This won't work:
// ❌ Twitter will show nothing
useSeoMeta({
ogTitle: 'My page',
ogImage: '/image.jpg'
})
This works:
// ✅ Twitter uses og:* tags as fallback
useSeoMeta({
twitterCard: 'summary_large_image', // Required - no fallback
ogTitle: 'My page',
ogImage: '/image.jpg'
})
Set both to avoid relying on fallback behavior:
// ✅ Explicit control
useSeoMeta({
twitterCard: 'summary_large_image',
twitterTitle: 'Twitter-specific title (70 chars)',
twitterImage: '/twitter-preview.jpg',
ogTitle: 'OpenGraph title can be longer',
ogImage: '/og-preview.jpg'
})
Use our Social Share Debugger to preview how your links appear on Twitter, Facebook, LinkedIn, and other platforms.
You can also use Twitter Card Validator directly.
The validator caches results. If you update tags and don't see changes:
?v=2Common issues:
Image not showing - Check that:
Wrong title/description - Twitter cached the old version. Add ?v=1 to the URL.
Card not appearing - You forgot twitterCard meta tag. It has no fallback.
Set different cards for different pages:
<!-- ~/pages/blog/[slug].vue -->
<script setup lang="ts">
const { data: post } = await useAsyncData('post', () =>
queryContent('blog', route.params.slug).findOne())
useSeoMeta({
twitterCard: 'summary_large_image',
twitterTitle: post.value.title,
twitterDescription: post.value.excerpt,
twitterImage: post.value.coverImage
})
</script>
Works best for blog posts with feature images, product pages with photos, landing pages with marketing visuals. Skip it for internal tools or password-protected content (Twitter can't fetch behind auth anyway).
Manually creating images for every page is tedious. The Nuxt OG Image module generates them automatically at build time: