~3 min read • Updated Oct 29, 2025
1. What Are opengraph-image and twitter-image?
These files define the preview image shown when a link to your site is shared on social media or messaging platforms. The browser uses metadata in the <head> to display the image.
2. Ways to Define Images
You can define social images in two ways:
- Using image files (.jpg, .png, .gif)
- Generating images with code (.js, .ts, .tsx)
3. Using Image Files
Place the image in the route segment:
opengraph-image.jpg→ for Open Graphtwitter-image.png→ for Twitteropengraph-image.alt.txt→ alt text for Open Graphtwitter-image.alt.txt→ alt text for Twitter
Size Limits:
- twitter-image: max 5MB
- opengraph-image: max 8MB
Example <head> Output:
<meta property="og:image" content="..." />
<meta name="twitter:image" content="..." />
<meta property="og:image:alt" content="About Acme" />
<meta name="twitter:image:alt" content="About Acme" />4. Generating Images with Code
Use the ImageResponse API from next/og:
// app/about/opengraph-image.tsx
import { ImageResponse } from 'next/og'
import { readFile } from 'node:fs/promises'
import { join } from 'node:path'
export const alt = 'About Acme'
export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'
export default async function Image() {
const font = await readFile(join(process.cwd(), 'assets/Inter-SemiBold.ttf'))
return new ImageResponse(
<div style={{
fontSize: 128,
background: 'white',
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}>
About Acme
</div>,
{
...size,
fonts: [{ name: 'Inter', data: font, style: 'normal', weight: 400 }],
}
)
}5. Input and Output Parameters
The export function can receive dynamic route params:
export default async function Image({ params }) {
const { slug } = await params
}Valid return types include:
- Blob
- ArrayBuffer
- TypedArray
- ReadableStream
- Response
6. Metadata Configuration
You can export metadata for the image:
export const alt = 'My images alt text'
export const size = { width: 1200, height: 630 }
export const contentType = 'image/png'7. Example with External Data
Generate the image based on API data:
// app/posts/[slug]/opengraph-image.tsx
export default async function Image({ params }) {
const { slug } = await params
const post = await fetch(`https://.../posts/${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>,
{ width: 1200, height: 630 }
)
}8. Using Local Assets
Read a local image and convert to base64:
const logoData = await readFile(join(process.cwd(), 'logo.png'), 'base64')
const logoSrc = `data:image/png;base64,${logoData}`Conclusion
With opengraph-image and twitter-image in Next.js, you can create rich, customizable social previews for every route. Whether using static files or dynamic code, these features give you full control over how your links appear when shared.
Written & researched by Dr. Shahin Siami