Index of every page on this site: llms.txt

Twitter Cards in Nuxt

Add twitter:card meta tags in Nuxt so shared links get a large image preview on X instead of a bare text link.
Harlan Wilton10 mins read Published Updated
What you'll learn
  • Set twitterCard explicitly for the card type you want
  • This guide uses summary_large_image with an example wide image
  • Set explicit X titles, descriptions, and image URLs; test the shared URL

Set X metadata alongside Open Graph tags. Test each platform separately.

Use twitter:card to declare the card type. A metadata example does not guarantee that X will display a preview.

<script setup lang="ts">
useSeoMeta({
  twitterCard: 'summary_large_image',
  twitterImage: 'https://example.com/social-preview.jpg',
  twitterTitle: 'Your page title',
  twitterDescription: 'Your page description'
})
</script>

Card Types

These are card type values you may encounter. This example uses summary_large_image:

summary_large_image: a card type for a large image preview.

useSeoMeta({
  twitterCard: 'summary_large_image',
  twitterImage: 'https://example.com/preview.jpg' // Example wide preview image
})

summary - Small square thumbnail (1:1 aspect ratio). Don't use this unless you specifically want a smaller preview.

useSeoMeta({
  twitterCard: 'summary',
  twitterImage: 'https://example.com/icon.jpg' // Example square preview image
})

player - Embedded video/audio player. Check current X requirements before using this type.

app - Mobile app install prompts. Check current X requirements before using this type.

Most sites should only use summary_large_image.

Required Tags

This example sets the card type, title, and image explicitly:

useSeoMeta({
  twitterCard: 'summary_large_image',
  twitterTitle: 'Page title',
  twitterImage: 'https://example.com/image.jpg' // Must be absolute URL
})

You can set the same image URL for X and Open Graph. Test each platform separately; preview cropping can differ.

Optional Tags

useSeoMeta({
  twitterCard: 'summary_large_image',
  twitterTitle: 'Your title',
  twitterImage: 'https://example.com/preview.jpg',
  twitterDescription: 'Accurate page description',
  twitterSite: '@yourhandle', // Your site's Twitter handle
  twitterCreator: '@authorhandle', // Content author's handle
  twitterImageAlt: 'Alt text' // Describe the image
})

Set twitterDescription explicitly when you need control over the authored description.

Open Graph Fallbacks

Set X metadata explicitly when you want predictable authoring. Test the public URL on X, since a local metadata preview does not prove the rendered card.

useSeoMeta({
  twitterCard: 'summary_large_image',
  twitterTitle: 'Page title',
  twitterDescription: 'Accurate page summary',
  twitterImage: 'https://example.com/preview.jpg',
  ogTitle: 'Page title',
  ogImage: 'https://example.com/preview.jpg'
})

Testing

Use our Social Share Debugger to inspect metadata. Test the shared URL on X to check the actual preview.

Compare the current page metadata with the shared preview. A preview mismatch can have several causes; a changed URL alone does not identify the cause.

Common issues:

Image not showing - Check that:

  • URL is absolute with HTTPS
  • Image response uses a supported format and reasonable file size
  • Image exists and returns 200 status
  • No robots.txt blocking Twitter's bot

Wrong title/description: inspect the public page response and the resolved X metadata before diagnosing the preview.

Card not appearing: check the card metadata and whether the public page and image are reachable.

Per-Page Cards

This initial-load example requires your /api/posts/:slug endpoint. Return the typed fields below, including an absolute image URL, or 404 for an absent post. Add route-change handling if the same page component stays mounted for another slug.

Set different cards for different pages:

pages/blog/[slug].vue
<script setup lang="ts">
const route = useRoute()
const { data: post, error } = await useFetch<{
  title: string
  description: string
  image: string
}>(`/api/posts/${encodeURIComponent(String(route.params.slug))}`)

if (error.value)
  throw error.value
if (!post.value) {
  throw createError({ statusCode: 404, statusMessage: 'Post not found' })
}

useSeoMeta({
  twitterCard: 'summary_large_image',
  twitterTitle: () => post.value?.title,
  twitterDescription: () => post.value?.description,
  twitterImage: () => post.value?.image,
})
</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).

To generate twitterImage instead of choosing one per page, see Automated OG Image Generation for the Nuxt OG Image module setup.

Checklist

Checklist
  • Set twitterCard explicitly
  • Use summary_large_image for most pages
  • Set explicit X and Open Graph tags for the platforms you use
  • Set twitterSite and twitterCreator for attribution
  • Test with the Social Share Debugger
Was this page helpful?