mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
### 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]>
212 lines
5.7 KiB
Plaintext
212 lines
5.7 KiB
Plaintext
---
|
||
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. |
|