---
title: "v6 to v7"
description: "Migrate Nuxt OG Image v6 to Nuxt OG Image v7."
canonical_url: "https://nuxtseo.com/docs/og-image/migration-guide/v7"
last_updated: "2026-10-09T08:13:15.598Z"
---

This guide covers upgrading from v6. If you use v5, follow the [v6 migration guide](/docs/og-image/migration-guide/v6) first.

## Update Node and Nuxt

Update your local, CI, and deployment environments before installing v7.

| Dependency    | Supported versions |
| ------------- | ------------------ |
| Node.js       | `^22.22.3          |
| Nuxt          | `^4.6.0            |
| `@unhead/vue` | `^3.4.2`           |

Nuxt 3 and Nuxt 4.0 through 4.5 are no longer supported.
If you pin `@unhead/vue` directly or through an override, update that pin too.
Nuxt 5 compatibility mode is optional. You do not need to enable it to use v7 on Nuxt 4.6.

From your application directory, update the module:

```bash
pnpm add nuxt-og-image@^7
```

Your existing renderer packages still apply. Keep the packages required by your [renderer](/docs/og-image/renderers).

## Move signing to NUXT_APP_SECRET

V6 generated an OG image secret during each build unless you supplied one.
V7 derives its signing key from Nuxt's private `runtimeConfig.appSecret`, using the purpose `nuxt-og-image:url-signing`.
Production runtime requests require a root secret of at least 32 characters when signing is enabled.
Missing or invalid secrets cause a `500` response, including on page requests.

If your application already sets `NUXT_APP_SECRET`, keep that value.
Otherwise, generate a root secret:

```bash
pnpm exec nuxt-og-image generate-secret
```

Set the printed `NUXT_APP_SECRET` value in your deployment environment.
On Cloudflare Workers, configure it as a secret binding named `NUXT_APP_SECRET`.
Keep the value private and stable across deployments and server instances within each environment.

V7 accepts `NUXT_OG_IMAGE_SECRET` when the application secret is empty.
This fallback also supports Cloudflare bindings and logs a deprecation warning once per runtime.
Rename the old environment key to `NUXT_APP_SECRET` when convenient. Keep its value unchanged.
A non-empty application secret always takes precedence. Invalid values still fail closed.
The fallback uses Nuxt's key derivation, so existing v6 signatures still become invalid.

Remove these old configuration settings if you use them:

- String values of `ogImage.security.secret`
- `runtimeConfig.ogImage.secret`

For example, remove the module-specific key:

```ts [nuxt.config.ts (v6)]
export default defineNuxtConfig({
  ogImage: {
    security: { secret: process.env.NUXT_OG_IMAGE_SECRET },
  },
})
```

Configure the root secret through your environment instead:

```bash [deployment environment (v7)]
NUXT_APP_SECRET=<your-generated-root-secret>
```

You do not need to declare `runtimeConfig.appSecret` in `nuxt.config.ts`.
Never put it under `runtimeConfig.public` or `app.config.ts`.

| Rendering mode                      | Root secret requirement                                                |
| ----------------------------------- | ---------------------------------------------------------------------- |
| Production runtime, signing enabled | Set it on every server instance                                        |
| Strict prerendering                 | Set the same value during the build and at runtime                     |
| Normal static prerendering          | No root secret needed during prerendering                              |
| `zeroRuntime: true`                 | No root secret needed unless strict prerendering produces signed URLs  |
| Development                         | Nuxt generates and persists a development secret if none is configured |

`ogImage.security.secret: false` still disables signing. It cannot be combined with `security.strict: true`.
See [Security](/docs/og-image/guides/security#disabling-signing) before choosing unsigned runtime URLs.

Existing v6 signatures become invalid because the derived signing key differs from the old key.
Rebuild prerendered pages and refresh cached HTML that contains dynamic OG image URLs.
After upgrading, fetch a page's new `og:image` URL and confirm it returns an image.
Changing `NUXT_APP_SECRET` later also invalidates signatures, sessions, and other values derived from that root secret.

If you purge images with `?purge=<token>`, use the derived OG image signing key, rather than the root secret.
If you use the legacy fallback, rename the environment key before using Nuxt's `deriveSecret()` directly.
In server code, derive it with:

```ts
import { deriveSecret } from 'nuxt/server'

const purgeToken = await deriveSecret('nuxt-og-image:url-signing')
```

Keep this token private. On Workers, run administrative purge code where Nuxt can resolve the root secret.
See [Runtime Cache](/docs/og-image/guides/runtime-cache#purging-the-cache) for CDN cache limits.

## Update server imports

If your server handlers call `getOgImageUrl`, import `defineEventHandler` from `nuxt/server`.
On Nuxt 4, the auto-imported h3 handler supplies a different event shape.
The helper now accepts Nuxt's portable `RequestEvent`.

```ts [server/api/og-image.get.ts]
import { defineEventHandler } from 'nuxt/server'
import { getOgImageUrl } from '#og-image/server'

export default defineEventHandler((event) => {
  return {
    url: getOgImageUrl(event, '/blog/hello', {
      component: 'OgImagePost',
      props: { title: 'My post' },
    }),
  }
})
```

Pass the current request event so signing can use request-specific bindings.
For your own event annotations, import `RequestEvent` from `nuxt/server` instead of using `H3Event`.

App composables remain auto-imported. For explicit imports, use `#og-image/app`:

```ts
import { defineOgImage } from '#og-image/app'
```

## Update @nuxt/fonts

Nuxt OG Image v7 reads fonts through the `fonts:resolved` hook of [@nuxt/fonts](https://fonts.nuxt.com).
Use an `@nuxt/fonts` release that provides this hook, and update both modules together.
Keep `global: true` on every font family used by an OG image.

If your `@nuxt/fonts` version does not have the hook, OG images use the bundled Inter font. The build warns:

```txt
@nuxt/fonts did not report any fonts, so OG images use the bundled Inter font. OG images need a @nuxt/fonts version with the `fonts:resolved` hook.
```

OG images load the font files that `@nuxt/fonts` serves in development, prerendering, and runtime rendering.
The webpack and rspack builders can use each configured family and weight.
See [Custom Fonts](/docs/og-image/guides/custom-fonts) for configuration and renderer format support.

## Restore the DevTools panel

If you use the OG Image DevTools panel, install the optional host module:

```bash
pnpm add -D nuxtseo-devtools-host@^1
```

Restart your development server after installation. The module loads the host automatically.
You do not need to add it to `modules`. Production image rendering does not require it.

## Check runtime cache storage

The default `runtimeCacheStorage: true` now uses a bounded 64 MiB memory cache when no Nitro cache mount is configured.
It evicts the least recently used images when full. Requests for evicted images render them again.
This limit covers stored image entries, rather than total server memory.

Configured Nitro cache mounts, named mounts, and explicit driver settings take precedence over this default.
If you need persistence across server restarts, keep or configure a persistent driver.

Storage drivers now receive a TTL from `cacheMaxAgeSeconds`, with a minimum of 60 seconds.
Drivers that support expiry can remove unread entries. Explicit `memory` storage still has no size limit in unstorage v1.17.5.
Review custom driver limits in the [Runtime Cache guide](/docs/og-image/guides/runtime-cache).

After upgrading, check a prerendered image, a signed runtime image, and each custom font family your templates use.

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
