Nuxt Config
Configure all options on this page under the ogImage key in your Nuxt config.
export default defineNuxtConfig({
ogImage: {
// options below go here, e.g.
defaults: {
extension: 'png',
},
},
})enabled
- Type:
boolean - Default:
true
Conditionally toggle the module.
defaults
- Type:
OgImageOptions - Default:
{ width: 1200, height: 600, extension: 'png', emojis: 'noto', cacheMaxAgeSeconds: 60 * 60 * 24 * 3 }
The default options to use when generating images.
See the defineOgImage documentation for more details.
compatibility
- Type:
{ dev?: CompatibilityFlags, runtime?: CompatibilityFlags, prerender?: CompatibilityFlags } - Default:
{}
Override the compatibility flags.
See the Renderers guide to learn more.
zeroRuntime
- Type:
boolean - Default:
false
Enable zero runtime mode. See the Zero Runtime documentation for more details.
satoriOptions
- Type:
SatoriOptions - Default:
{}
Options to pass to Satori when generating images. See the Satori docs.
resvgOptions
- Type:
ResvgRenderOptions - Default:
{}
Options to pass to Resvg when generating images. See the Resvg docs.
sharpOptions
- Type:
SharpOptions | true - Default:
undefined
Options to pass to Sharp when generating images. See the Sharp docs.
cacheVersion
- Type:
string | false - Default: module version
Custom version string for cache key namespacing.
By default, the module uses its version number, which invalidates the cache on module upgrades. Set a static value like 'v1' to persist the cache across module updates. Set to false to disable versioning entirely.
fontSubsets
- Type:
string[] - Default:
['latin']
Font subsets to download when resolving missing font families via fontless.
This option only controls which subsets the module downloads when supplementing missing families for the Satori renderer. Fonts from @nuxt/fonts always include all their available subsets.
export default defineNuxtConfig({
ogImage: {
fontSubsets: ['latin', 'devanagari', 'cyrillic']
}
})componentDirs
- Type:
string[] - Default:
['OgImage', 'OgImageCommunity', 'og-image', 'OgImageTemplate']
Extra component directories the module should use to resolve components.
runtimeCacheStorage
- Type:
boolean | string | (Record<string, any> & { driver: string }) - Default:
true
Modify the runtime cache behavior.
Passing false disables runtime image storage. Passing true uses configured Nitro cache storage when available.
Otherwise, the module uses a memory cache with a 64 MiB entry limit. Evicted images render again on request.
The limit does not cap total server memory. Explicit storage settings must provide their own limit or expiry.
To configure a storage driver directly, pass an object with its driver name and options.
See the Runtime Cache guide for storage limits and persistent drivers.
export default defineNuxtConfig({
ogImage: {
runtimeCacheStorage: {
driver: 'redis',
host: 'localhost',
port: 6379,
password: 'password'
}
}
})buildCache
- Type:
boolean | { base?: string } - Default:
false
Enable persistent build cache for CI environments. Caches rendered images to disk so they persist between CI runs.
The cache key includes the options hash, component template hash, and module version, ensuring automatic invalidation when any of these change.
export default defineNuxtConfig({
ogImage: {
buildCache: true
// or with custom directory:
// buildCache: { base: '.cache/og-image' }
}
})Default cache directory: node_modules/.cache/nuxt-seo/og-image/
See the Build Cache guide for CI configuration examples.
app.cdnURL
Prerendered image URLs use Nuxt's app.cdnURL when configured.
The images stay in .output/public/_og/s/.
Your deployment must serve the public folder from that CDN.
export default defineNuxtConfig({
app: {
cdnURL: 'https://assets.example.com/static/'
}
})Image URLs use https://assets.example.com/static/_og/s/....
The CDN URL replaces app.baseURL, matching Nuxt's public asset behavior.
Runtime image URLs and resolver URLs stay on the app origin.
If bucket publishing succeeds, publish.baseURL takes precedence.
Otherwise, the local static file uses app.cdnURL.
This setting changes delivery URLs. Your CDN's cache headers control static file freshness.
Nuxt Image can display published URLs with <NuxtImg> when its provider allows the bucket's domain.
Keep OG tags on the published URL. Nuxt Image providers handle image URLs, while Nitro storage handles uploads.
publish
- Type:
{ storage: string, baseURL: string } - Default: disabled
Upload rendered images to public object storage through a Nitro storage mount.
After upload, prerendered og:image and twitter:image tags use the public URL.
Runtime pages use a locally known public URL or the app image URL.
SSR reads only a local URL cache. It never contacts the bucket.
An image request redirects to a fresh published image when storage confirms that the object exists.
Otherwise, it returns image bytes and publishes them in the background through event.waitUntil().
Successful image lookups and uploads update that instance's local URL cache.
Cold Workers and new server instances start with the app image URL.
During nuxt dev, images use local app URLs and publishing stays disabled.
Prerender builds can publish images through nitro.devStorage.
Setup checks the public URL's syntax. It does not contact the bucket or upload a test image. The URL must use HTTP or HTTPS without credentials, query parameters, or a fragment. A missing storage mount produces a build warning.
If the local URL cache entry expires or is evicted, pages return to the app URL. The next image request can publish the image again.
For S3-compatible endpoints, use Nitro's s3 driver and install aws4fetch: pnpm add aws4fetch.
export default defineNuxtConfig({
ogImage: {
publish: {
storage: 'og-image-public',
baseURL: 'https://images.example.com'
}
},
nitro: {
storage: {
'og-image-public': {
driver: 's3',
endpoint: process.env.OG_STORAGE_ENDPOINT,
bucket: process.env.OG_STORAGE_BUCKET,
region: process.env.OG_STORAGE_REGION,
accessKeyId: process.env.OG_STORAGE_ACCESS_KEY,
secretAccessKey: process.env.OG_STORAGE_SECRET_KEY
}
}
}
})The mount must support raw writes. During prerendering, Node must be able to access it. The public URL must serve the mount's keys, including any driver prefix.
Cloudflare R2
Create an R2 bucket named og-images and connect a public domain, such as images.example.com.
Use a custom domain for production. Cloudflare's managed r2.dev URL supports development traffic.
See public R2 buckets.
Install the S3 driver's dependency:
pnpm add aws4fetchCreate bucket-scoped S3 credentials with read and write access. Set these server-only variables in your build environment:
R2_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
R2_BUCKET=og-images
R2_ACCESS_KEY=<access-key-id>
R2_SECRET_KEY=<secret-access-key>Use the R2 binding at runtime and S3 during prerender builds:
export default defineNuxtConfig({
ogImage: {
publish: { storage: 'og-image-public', baseURL: 'https://images.example.com' }
},
nitro: {
preset: 'cloudflare-module',
storage: {
'og-image-public': { driver: 'cloudflare-r2-binding', binding: 'OG_IMAGES' }
}
},
$production: {
nitro: {
devStorage: {
'og-image-public': {
driver: 's3',
endpoint: process.env.R2_ENDPOINT,
bucket: process.env.R2_BUCKET,
region: 'auto',
accessKeyId: process.env.R2_ACCESS_KEY,
secretAccessKey: process.env.R2_SECRET_KEY
}
}
}
}
})The $production block keeps S3 settings out of nuxt dev.
Local development needs no S3 credentials and does not write to the bucket.
Both configurations use the same bucket and storage mount name.
Add the binding and public assets to your Worker configuration:
name = "nuxt-og-image"
main = ".output/server/index.mjs"
compatibility_date = "2026-10-09"
compatibility_flags = [ "nodejs_compat" ]
[assets]
directory = ".output/public"
binding = "ASSETS"
[[r2_buckets]]
binding = "OG_IMAGES"
bucket_name = "og-images"This example writes images at the bucket root.
If your storage driver uses an object prefix, include that prefix in publish.baseURL.
The public URL must serve the exact object key. Fetching the bucket root does not verify image delivery.
Manifest expiry
Each image has a manifest with its object key and expiry time.
The manifest key includes the site origin, image options, the component template hash, and cacheVersion.
Signed and unsigned requests share the same manifest key.
Builds reuse images for cacheMaxAgeSeconds without rendering them again.
If the manifest expires or the object disappears, prerendering renders it again.
Setting cacheMaxAgeSeconds to zero disables reuse.
Set the default lifetime in nuxt.config.ts:
export default defineNuxtConfig({
ogImage: { cacheMaxAgeSeconds: 3600 }
})For one image, pass the lifetime in the third argument:
defineOgImage('MyImage.satori', { title: 'Hello' }, { cacheMaxAgeSeconds: 300 })The second argument contains component props. A lifetime placed there does not configure caching.
Runtime buffer cache hits keep their original expiry when publishing. They do not extend the manifest's lifetime. The local URL cache holds up to 1,000 entries per app instance. Each entry expires after 60 seconds or at the manifest's expiry, whichever comes first. An image redirect's cache lifetime cannot exceed the manifest's remaining lifetime. Image requests check storage with a 500 ms deadline before using the normal image handler. This deadline stops waiting. It does not cancel the storage request. Concurrent image requests share one background publication per image in the same app instance. Storage failures keep image responses working through the app.
Image object names contain the SHA-256 hash of their bytes. Changed bytes get a new URL. Refreshing a manifest leaves older pages' images available. Objects have no storage TTL, and the module never deletes them.
Keep objects while any deployed page or cached HTML can reference them. If you use bucket lifecycle rules, keep objects for that long.
Upload headers and failures
Uploads pass content type and immutable cache headers through the driver's httpMetadata options.
The R2 binding driver supports these options.
The S3 driver ignores them.
Configure the public bucket or CDN to serve image MIME types and Cache-Control: public, max-age=31536000, immutable.
If storage is missing or fails, prerendering keeps the static image file.
Its URL uses app.cdnURL when configured.
Runtime pages and image responses also keep working through the app.
Runtime publishing failures produce one warning per app instance, with the storage failure reason.
If publishing succeeds, prerendering skips the local static image file.
cacheMaxAgeSeconds
- Type:
number - Default:
60 * 60 * 24 * 3(3 days)
Default cache duration in seconds for generated OG images. Controls the internal storage TTL and HTTP Cache-Control header duration (max-age / s-maxage). Can be overridden per image via defineOgImage's cacheMaxAgeSeconds option.
export default defineNuxtConfig({
ogImage: {
cacheMaxAgeSeconds: 60 * 60 * 24 // 1 day
}
})See the Runtime Cache guide for details.
warnMissingSuffix
- Type:
boolean - Default:
true
Warn about OG Image components missing the renderer suffix (.satori.vue, .takumi.vue, .browser.vue) in dev mode. Set to false to suppress warnings for legacy or test components.
includeTwitter
- Type:
boolean - Default:
true
Include Twitter card meta tags (twitter:card, twitter:image, etc) alongside the Open Graph image tags. Set to false to only emit og:image tags.
When unset, the module respects seo.automaticTwitterTags from nuxt-seo-kit before falling back to true.
export default defineNuxtConfig({
seo: {
automaticTwitterTags: false
},
ogImage: {
// optional explicit override, takes precedence over seo.automaticTwitterTags
includeTwitter: false
}
})emojiStrategy
- Type:
'auto' | 'local' | 'fetch' - Default:
'fetch'
defaults.emojis: false to disable emoji support entirely.browser
- Type:
BrowserConfig - Default:
undefined
Set browser: true to enable defineOgImageScreenshot() with automatic local browser selection.
A browser provider object also enables screenshots.
If you omit this option or set it to false, screenshot calls throw a setup error.
Component images still select their renderer through the .browser.vue suffix.
export default defineNuxtConfig({
ogImage: {
browser: true
}
})Prerender screenshot pages for production. This option does not add browser support to incompatible hosts.
To configure a browser provider, pass an object. For Cloudflare deployments, specify the browser binding name.
export default defineNuxtConfig({
ogImage: {
browser: {
provider: 'cloudflare',
binding: 'BROWSER'
}
}
})See the Browser Renderer guide for more details.
security
- Type:
object
Security limits for image generation. See the Security Guide for full details.
secret: Setfalseto disable URL signing. Otherwise, the module derives a signing secret from NuxtruntimeConfig.appSecret. SetNUXT_APP_SECRETin production. See the Security Guide.maxDimension: Maximum width or height in pixels. Default2048.maxDpr: Maximum device pixel ratio (Takumi renderer). Default2.renderTimeout: Milliseconds before the render is aborted with a408response. Default15000.maxQueryParamSize: Maximum query string length (in characters) for runtime requests. Returns400when exceeded. Defaultnull(no limit).restrictRuntimeImagesToOrigin: Restrict runtime image generation to requests whoseHostheader matches allowed hosts. Defaultfalse. See the Security Guide for details.strict: Enable strict security mode. Requiressecret, disables the deprecatedhtmloption, defaultsmaxQueryParamSizeto2048, and enablesrestrictRuntimeImagesToOrigin. Defaultfalse. See the Security Guide for details.
NUXT_APP_SECRET=<your-secret>export default defineNuxtConfig({
ogImage: {
security: {
strict: true,
}
}
})debug
- Type:
boolean - Default:
false
Enables debug logs and a debug endpoint.