OG Images & Schema

Dynamic Social Previews via @nuxt/og-image

OG Images & Schema

nuxt-og-image generates social-preview images at build or runtime using a Vue template — no Puppeteer, no separate service.

4 min read Level 3/5 #nuxt#seo#og
What you'll learn
  • Install nuxt-og-image
  • Define a default OG template
  • Override per page with defineOgImageComponent

Hand-rolling OG images means designing 1200x630 PNGs for every blog post. The nuxt-og-image module renders them from a Vue component instead — at the edge, on demand.

Install

npx nuxi module add nuxt-og-image

The module registers a runtime route at /__og-image__/<path>/og.png. When a crawler hits that URL, Nuxt renders the matching component to PNG and caches it.

A Default Template

Set a site-wide default in app.vue or any layout — pages without their own OG image get this one with the page title injected automatically.

<script setup lang="ts">
defineOgImageComponent('NuxtSeo', {
  title: 'MySite',
  description: 'A great Nuxt site',
  theme: '#00DC82',
})
</script>

NuxtSeo is a built-in template; you can also point at any component in components/OgImage/.

Per-Page Override

Inside a blog post, call defineOgImageComponent again with post-specific data:

<script setup lang="ts">
const { data: post } = await useFetch(`/api/posts/${useRoute().params.slug}`)

defineOgImageComponent('NuxtSeo', {
  title: post.value!.title,
  description: post.value!.excerpt,
  icon: 'simple-icons:nuxt',
})
</script>

Custom Component

Drop a components/OgImage/MyCard.vue and reference it by name. Use plain HTML and CSS — the module renders the component to SVG, then to PNG.

<template>
  <div class="og">
    <h1>{{ title }}</h1>
    <p>{{ subtitle }}</p>
  </div>
</template>

<script setup lang="ts">
defineProps<{ title: string; subtitle: string }>()
</script>

<style scoped>
.og { width: 1200px; height: 630px; padding: 80px; background: #00DC82; }
</style>

Then use it: defineOgImageComponent('MyCard', { title: 'Hi', subtitle: 'World' }).

Build-Time vs Runtime

By default images render on demand. For SSG, the module pre-renders OG images for every page during nuxi generate — your hosted output ships static PNGs.

error.vue — Polishing 404s and 500s →