Index of every page on this site: llms.txt

Nuxt OG Image supports three rendering engines, each with different trade-offs. We recommend Takumi for the best balance of speed and CSS support.

All renderers share core features: Tailwind CSS support, custom fonts (Google Fonts, local, variable, WOFF2), emoji rendering, and edge runtime compatibility.

Comparison

FeatureTakumiSatoriBrowser
Recommended
SpeedFastest (2-10x)FastSlow
Edge Runtime✅✅Cloudflare only
CSS SupportCompletePartialFull
Gradients✅✅✅
Opacity✅✅✅
Flexbox✅✅✅
CSS Grid✅❌✅
Shadows✅Partial✅
Transforms✅ 2D/3D❌✅
Filters✅❌✅
Emoji✅ COLR fonts✅ 11 families✅
FontsWOFF2, variableGoogle Fonts, localAny
Dependencies@takumi-rs/core
@takumi-rs/wasm
satori
@resvg/resvg-js
@resvg/resvg-wasm
playwright-core

Environment Compatibility

EnvironmentSatoriTakumiBrowser
Node.js✅✅ @takumi-rs/core✅ playwright-core
Prerender / CI✅✅✅ Auto-installs
AWS Lambda✅✅❌ Binary too large
Vercel✅✅❌
Vercel Edge✅ Wasm✅ Wasm❌
Netlify✅✅❌
Netlify Edge✅ Wasm✅ Wasm❌
Cloudflare Workers✅ Wasm✅ Wasm✅ Browser Rendering
Cloudflare Pages✅ Wasm✅ Wasm✅ Browser Rendering
StackBlitz✅ Wasm✅ Wasm❌

Binding Types

Each renderer can use different bindings depending on the environment:

  • node - Default Node.js binding, best performance
  • Wasm - WebAssembly binding for edge runtimes and workers
  • wasm-fs - WebAssembly with filesystem access (dev environments like StackBlitz)
  • false - Disabled

Provider Notes

AWS Lambda, Netlify, Vercel (Serverless)

  • Browser unavailable (binary too large)
  • Sharp unavailable (post-install script issues)

Vercel Edge, Netlify Edge

  • Satori and Takumi use Wasm automatically
  • Browser and Sharp unavailable

Cloudflare Workers/Pages

Overriding Compatibility

You can override the default compatibility settings:

nuxt.config.ts
export default defineNuxtConfig({
  ogImage: {
    compatibility: {
      // disable browser for prerendering (skips install in CI)
      prerender: {
        browser: false
      },
      // force WASM binding at runtime
      runtime: {
        resvg: 'wasm'
      }
    }
  }
})

Component Naming Convention

OG Image components must include the renderer in their filename:

components/OgImage/
  MyTemplate.takumi.vue    # Takumi renderer (recommended)
  MyTemplate.satori.vue    # Satori renderer
  Screenshot.browser.vue   # Browser renderer

This enables:

  • Automatic renderer detection - no need to specify renderer in defineOgImage()
  • Tree-shaking - unused renderer code is excluded from production builds

The module supports multiple renderers for the same component name.

You can create both MyTemplate.satori.vue and MyTemplate.takumi.vue. When calling defineOgImage('MyTemplate'), the module uses the first registered variant. To select a specific renderer, use dot notation:

defineOgImage('MyTemplate.takumi')

You can also use PascalCase: defineOgImage('MyTemplateTakumi').

Choosing a Renderer

The component filename suffix determines the renderer - there is no global defaults.renderer config.

Takumi is the recommended renderer. It's 2-10x faster than Satori with complete CSS support including gradients, shadows, opacity, CSS Grid, transforms, and filters:

components/OgImage/MyTemplate.takumi.vue

Use Satori

Satori requires satori and @resvg/resvg-js (or @resvg/resvg-wasm for edge runtimes) as peer dependencies. It has good CSS support for most templates:

components/OgImage/MyTemplate.satori.vue

Use Browser

Choose Browser when you need full CSS support and are prerendering all images at build time:

components/OgImage/MyTemplate.browser.vue
Browser is slow and doesn't work on most hosting providers at runtime. Only use it for prerendering.

Zero Runtime Mode

If you're prerendering all OG images at build time, enable Zero Runtime mode to remove all renderer code from your production bundle (81% smaller Nitro output).

nuxt.config.ts
export default defineNuxtConfig({
  ogImage: {
    zeroRuntime: true
  }
})

This works with any renderer and is ideal when your OG images don't change dynamically.

Was this page helpful?