---
title: "Twitter Cards in Nuxt"
description: "Add twitter:card meta tags in Nuxt so shared links get a large image preview on X instead of a bare text link."
canonical_url: "https://nuxtseo.com/learn-seo/nuxt/mastering-meta/twitter-cards"
last_updated: "2026-10-05"
---

> Index of every page on this site: [llms.txt](https://nuxtseo.com/llms.txt)

::key-takeaways
- 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](https://nuxtseo.com/learn-seo/nuxt/mastering-meta/open-graph). Test each platform separately.

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

```vue
<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.

```vue
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.

```vue
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:

```vue
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](https://nuxtseo.com/learn-seo/nuxt/mastering-meta/open-graph#open-graph-tags-image-requirements). Test each platform separately; preview cropping can differ.

## Optional Tags

```vue
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.

```ts
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](https://nuxtseo.com/tools/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:

```vue [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](https://nuxtseo.com/learn-seo/nuxt/mastering-meta/open-graph#automated-og-image-generation) for the Nuxt OG Image module setup.

## Checklist

::checklist{#nuxt-twitter-cards}
- 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](https://nuxtseo.com/tools/social-share-debugger)
::

## Sitemap

See the full [sitemap](https://nuxtseo.com/sitemap.md) for all pages.
