@vercel/og
Generate Open Graph images with Vercel’s Edge Function.
Basic Usage
Install @vercel/og
, then use it inside Edge API routes in your Next.js project:
import { ImageResponse } from '@vercel/og'
export const config = {
runtime: 'experimental-edge',
}
export default function () {
return new ImageResponse(
(
<div
style={{
fontSize: 128,
background: 'white',
width: '100%',
height: '100%',
}}
>
Hello!
</div>
)
)
}
The React element will be rendered and responded as a PNG from that Edge Function endpoint. For more details and restrictions in image generation, see Satori.
API Reference
@vercel/og
only supports the Edge Runtime. The Node.js runtime will not work.
The package exposes an ImageResponse
constructor, with the following options available:
import { ImageResponse } from '@vercel/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
status?: number = 200
statusText?: string
headers?: Record<string, string>
},
)
When running in production, these headers will be included by @vercel/og
:
'content-type': 'image/png',
'cache-control': 'public, immutable, no-transform, max-age=31536000',
During development, the cache-control: no-cache, no-store
header is used instead.
You can see the Code Examples section below to see more details.
Code Examples
Hello World
import { ImageResponse } from '@vercel/og'
export const config = {
runtime: 'experimental-edge',
}
export default function () {
return new ImageResponse(
(
<div
style={{
fontSize: 128,
background: 'white',
width: '100%',
height: '100%',
}}
>
Hello!
</div>
)
)
}
Dynamic Image
import { ImageResponse } from '@vercel/og'
export const config = {
runtime: 'experimental-edge',
}
export default async function (req) {
const { searchParams } = req.nextUrl
const username = searchParams.get('username')
if (!username) {
return new ImageResponse(<>Visit with "?username=vercel"</>)
}
return new ImageResponse(
(
<div
style={{
fontSize: 60,
color: 'black',
background: '#f6f6f6',
width: '100%',
height: '100%',
paddingTop: 50,
flexDirection: 'column',
justifyContent: 'center',
alignContent: 'center',
alignItems: 'center',
}}
>
<img
width='256'
height='256'
src={`https://github.com/${username}.png`}
style={{
borderRadius: 128,
}}
/>
<p>github.com/{username}</p>
</div>
)
)
}
Emoji
import { ImageResponse } from '@vercel/og'
export const config = {
runtime: 'experimental-edge',
}
export default async function () {
return new ImageResponse(
(
<div
style={{
fontSize: 100,
color: 'black',
background: 'white',
width: '100%',
height: '100%',
padding: '0 200px',
textAlign: 'center',
justifyContent: 'center',
alignContent: 'center',
}}
>
👋, 🌎
</div>
),
{
width: 1200,
height: 600,
emoji: 'twemoji',
}
)
}
Image SVG
import { ImageResponse } from '@vercel/og'
export const config = {
runtime: 'experimental-edge',
}
export default async function () {
return new ImageResponse(
(
<div
style={{
fontSize: 40,
color: 'black',
background: 'white',
width: '100%',
height: '100%',
padding: '0 200px',
textAlign: 'center',
justifyContent: 'center',
alignContent: 'center',
}}
>
<svg
height={80}
viewBox="0 0 75 65"
fill="black"
style={{ margin: '0 75px' }}
>
<path d="M37.59.25l36.95 64H.64l36.95-64z"></path>
</svg>
</div>
)
)
}
Different Languages
import { ImageResponse } from '@vercel/og'
export const config = {
runtime: 'experimental-edge',
}
export default async function () {
return new ImageResponse(
(
<div
style={{
fontSize: 40,
color: 'black',
background: 'white',
width: '100%',
height: '100%',
padding: '0 200px',
textAlign: 'center',
justifyContent: 'center',
alignContent: 'center',
}}
>
👋 Hello 你好 नमस्ते こんにちは สวัสดีค่ะ 안녕 добрий день Hallá
</div>
),
{
width: 1200,
height: 600,
}
)
}
Acknowledgements
This project will not be possible without the following projects: