Files
d44ee523d8 docs(opengraph-image): load assets at module scope to keep route static under Cache Components (#95246)
### What?

Document loading request-independent assets at module scope, and update
the OG image examples to follow it.

### Why?

Reading a local asset inside the component is async I/O during render,
so the route defers to request time. A top-level `await` at module scope
keeps the route prerendered without reaching for `use cache`. The
pattern previously only lived as an inline snippet in the OG image docs.

### How?

- Add an "Asynchronous I/O at module scope" section to the Cache
Components guide as the canonical explanation.
- Load fonts and local assets at module scope in `opengraph-image.mdx`
and `image-response.mdx`, and link both to the new section.

<!-- NEXT_JS_LLM_PR -->

---------

Co-authored-by: Joseph <[email protected]>
2026-07-09 19:59:00 +02:00

212 lines
5.7 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: ImageResponse
description: API Reference for the ImageResponse constructor.
---
The `ImageResponse` constructor allows you to generate dynamic images using JSX and CSS. This is useful for generating social media images such as Open Graph images, Twitter cards, and more.
## Reference
### Parameters
The following parameters are available for `ImageResponse`:
```jsx
import { ImageResponse } from 'next/og'
new ImageResponse(
element: ReactElement,
options: {
width?: number = 1200
height?: number = 630
emoji?: 'twemoji' | 'blobmoji' | 'noto' | 'openmoji' = 'twemoji',
fonts?: {
name: string,
data: ArrayBuffer,
weight: number,
style: 'normal' | 'italic'
}[]
debug?: boolean = false
// Options that will be passed to the HTTP response
status?: number = 200
statusText?: string
headers?: Record<string, string>
},
)
```
> Examples are available in the [Vercel OG Playground](https://og-playground.vercel.app/).
### Supported HTML and CSS features
`ImageResponse` supports common CSS properties including flexbox and absolute positioning, custom fonts, text wrapping, centering, and nested images.
Please refer to [Satori’s documentation](https://github.com/vercel/satori#css) for a list of supported HTML and CSS features.
## Behavior
- `ImageResponse` uses [@vercel/og](https://vercel.com/docs/concepts/functions/edge-functions/og-image-generation), [Satori](https://github.com/vercel/satori), and Resvg to convert HTML and CSS into PNG.
- Only flexbox and a subset of CSS properties are supported. Advanced layouts (e.g. `display: grid`) will not work.
- Maximum bundle size of `500KB`. The bundle size includes your JSX, CSS, fonts, images, and any other assets. If you exceed the limit, consider reducing the size of any assets or fetching at runtime.
- Only `ttf`, `otf`, and `woff` font formats are supported. To maximize the font parsing speed, `ttf` or `otf` are preferred over `woff`.
## Examples
### Route Handlers
`ImageResponse` can be used in Route Handlers to generate images dynamically at request time.
```js filename="app/api/route.js"
import { ImageResponse } from 'next/og'
export async function GET() {
try {
return new ImageResponse(
(
<div
style={{
height: '100%',
width: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'white',
padding: '40px',
}}
>
<div
style={{
fontSize: 60,
fontWeight: 'bold',
color: 'black',
textAlign: 'center',
}}
>
Welcome to My Site
</div>
<div
style={{
fontSize: 30,
color: '#666',
marginTop: '20px',
}}
>
Generated with Next.js ImageResponse
</div>
</div>
),
{
width: 1200,
height: 630,
}
)
} catch (e) {
console.log(`${e.message}`)
return new Response(`Failed to generate the image`, {
status: 500,
})
}
}
```
### File-based Metadata
You can use `ImageResponse` in a [`opengraph-image.tsx`](/docs/app/api-reference/file-conventions/metadata/opengraph-image) file to generate Open Graph images at build time or dynamically at request time.
```tsx filename="app/opengraph-image.tsx"
import { ImageResponse } from 'next/og'
// Image metadata
export const alt = 'My site'
export const size = {
width: 1200,
height: 630,
}
export const contentType = 'image/png'
// Image generation
export default async function Image() {
return new ImageResponse(
(
// ImageResponse JSX element
<div
style={{
fontSize: 128,
background: 'white',
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
My site
</div>
),
// ImageResponse options
{
// For convenience, we can re-use the exported opengraph-image
// size config to also set the ImageResponse's width and height.
...size,
}
)
}
```
### Custom fonts
You can use custom fonts in your `ImageResponse` by providing a `fonts` array in the options. The font doesn't depend on request data, so read it once at module scope. See [Predictable values](/docs/app/getting-started/caching#predictable-values).
```tsx filename="app/opengraph-image.tsx"
import { ImageResponse } from 'next/og'
import { readFile } from 'node:fs/promises'
import { join } from 'node:path'
// Image metadata
export const alt = 'My site'
export const size = {
width: 1200,
height: 630,
}
export const contentType = 'image/png'
const interSemiBold = await readFile(
join(process.cwd(), 'assets/Inter-SemiBold.ttf')
)
// Image generation
export default async function Image() {
return new ImageResponse(
(
// ...
),
// ImageResponse options
{
// For convenience, we can re-use the exported opengraph-image
// size config to also set the ImageResponse's width and height.
...size,
fonts: [
{
name: 'Inter',
data: interSemiBold,
style: 'normal',
weight: 400,
},
],
}
)
}
```
## Version History
| Version | Changes |
| --------- | ----------------------------------------------------- |
| `v14.0.0` | `ImageResponse` moved from `next/server` to `next/og` |
| `v13.3.0` | `ImageResponse` can be imported from `next/server`. |
| `v13.0.0` | `ImageResponse` introduced via `@vercel/og` package. |