opengraph-image and twitter-image
The opengraph-image
and twitter-image
file conventions allow you to set Open Graph and Twitter images for a route segment.
They are useful for setting the images that appear on social networks and messaging apps when a user shares a link to your site.
There are two ways to set Open Graph and Twitter images:
Image files (.jpg, .png, .gif)
Use an image file to set a route segment’s shared image by placing an opengraph-image
or twitter-image
image file in the segment.
Next.js will evaluate the file and automatically add the appropriate tags to your app’s <head>
element.
File convention | Supported file types |
---|---|
opengraph-image |
.jpg , .jpeg , .png , .gif |
twitter-image |
.jpg , .jpeg , .png , .gif |
opengraph-image.alt |
.txt |
twitter-image.alt |
.txt |
opengraph-image
Add an opengraph-image.(jpg|jpeg|png|gif)
image file to any route segment.
twitter-image
Add a twitter-image.(jpg|jpeg|png|gif)
image file to any route segment.
opengraph-image.alt.txt
Add an accompanying opengraph-image.alt.txt
file in the same route segment as the opengraph-image.(jpg|jpeg|png|gif)
image it’s alt text.
opengraph-image.alt.txt
About Acme
twitter-image.alt.txt
Add an accompanying twitter-image.alt.txt
file in the same route segment as the twitter-image.(jpg|jpeg|png|gif)
image it’s alt text.
twitter-image.alt.txt
About Acme
Generate images using code (.js, .ts, .tsx)
In addition to using literal image files, you can programmatically generate images using code.
Generate a route segment’s shared image by creating an opengraph-image
or twitter-image
route that default exports a function.
File convention | Supported file types |
---|---|
opengraph-image |
.js , .ts , .tsx |
twitter-image |
.js , .ts , .tsx |
Good to know
- By default, generated images are statically optimized ↗ (generated at build time and cached) unless they use dynamic functions ↗ or uncached data.
- You can generate multiple Images in the same file using
generateImageMetadata
.
The easiest way to generate an image is to use the ImageResponse API from next/server
.
app/about/opengraph-image.tsx
import { ImageResponse } from 'next/server'
// Route segment config
export const runtime = 'edge'
// Image metadata
export const alt = 'About Acme'
export const size = {
width: 1200,
height: 630,
}
export const contentType = 'image/png'
// Image generation
export default async function Image() {
// Font
const interSemiBold = fetch(
new URL('./Inter-SemiBold.ttf', import.meta.url)
).then((res) => res.arrayBuffer())
return new ImageResponse(
(
// ImageResponse JSX element
<div
style={{
fontSize: 128,
background: 'white',
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
About Acme
</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,
fonts: [
{
name: 'Inter',
data: await interSemiBold,
style: 'normal',
weight: 400,
},
],
}
)
}
Props
The default export function receives the following props:
params
(optional)
An object containing the dynamic route parameters ↗ object from the root segment down to the segment opengraph-image
or twitter-image
is colocated in.
app/shop/[slug]/opengraph-image.tsx
export default function Image({ params }: { params: { slug: string } }) {
// ...
}
Route | URL | params |
---|---|---|
app/shop/opengraph-image.js |
/shop |
undefined |
app/shop/[slug]/opengraph-image.js |
/shop/1 |
{ slug: '1' } |
app/shop/[tag]/[item]/opengraph-image.js |
/shop/1/2 |
{ tag: '1', item: '2' } |
app/shop/[...slug]/opengraph-image.js |
/shop/1/2 |
{ slug: ['1', '2'] } |
Returns
The default export function should return a Blob
| ArrayBuffer
| TypedArray
| DataView
| ReadableStream
| Response
.
Good to know:
ImageResponse
satisfies this return type.
Config exports
You can optionally configure the image’s metadata by exporting alt
, size
, and contentType
variables from opengraph-image
or twitter-image
route.
Option | Type |
---|---|
alt |
string |
size |
{ width: number; height: number } |
contentType |
string - image MIME type ↗ |
alt
opengraph-image.tsx / twitter-image.tsx
export const alt = 'My images alt text'
export default function Image() {}
size
opengraph-image.tsx / twitter-image.tsx
export const size = { width: 1200, height: 630 }
export default function Image() {}
contentType
opengraph-image.tsx / twitter-image.tsx
export const contentType = 'image/png'
export default function Image() {}
Route Segment Config
opengraph-image
and twitter-image
are specialized Route Handlers that can use the same route segment configuration ↗ options as Pages and Layouts.
Option | Type | Default |
---|---|---|
dynamic ↗ |
`‘auto’ | ‘force-dynamic’ |
revalidate ↗ |
`false | ‘force-cache’ |
runtime ↗ |
`‘nodejs’ | ’edge'` |
preferredRegion ↗ |
`‘auto’ | ‘global’ |
app/opengraph-image.tsx
export const runtime = 'edge'
export default function Image() {}
Examples
Using external data
This example uses the params
object and external data to generate the image.
Good to know: By default, this generated image will be statically optimized ↗. You can configure the individual
fetch
options
↗ or route segments options ↗ to change this behavior.
app/posts/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/server'
export const runtime = 'edge'
export const alt = 'About Acme'
export const size = {
width: 1200,
height: 630,
}
export const contentType = 'image/png'
export default async function Image({ params }: { params: { slug: string } }) {
const post = await fetch(`https://.../posts/${params.slug}`).then((res) =>
res.json()
)
return new ImageResponse(
(
<div
style={{
fontSize: 48,
background: 'white',
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
{post.title}
</div>
),
{
...size,
}
)
}
Version History
Version | Changes |
---|---|
v13.3.0 |
opengraph-image and twitter-image introduced. |