Skip to content
App Router...Metadata Filesopengraph-image and twitter-image

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 conventionSupported 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.

<head> output
<meta property="og:image" content="<generated>" />
<meta property="og:image:type" content="<generated>" />
<meta property="og:image:width" content="<generated>" />
<meta property="og:image:height" content="<generated>" />

twitter-image

Add a twitter-image.(jpg|jpeg|png|gif) image file to any route segment.

<head> output
<meta name="twitter:image" content="<generated>" />
<meta name="twitter:image:type" content="<generated>" />
<meta name="twitter:image:width" content="<generated>" />
<meta name="twitter:image:height" content="<generated>" />

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
<head> output
<meta property="og:image:alt" content="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
<head> output
<meta property="twitter:image:alt" content="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 conventionSupported file types
opengraph-image.js, .ts, .tsx
twitter-image.js, .ts, .tsx

Good to know

The easiest way to generate an image is to use the ImageResponse API from next/og.

app/about/opengraph-image.tsx
import { ImageResponse } from 'next/og'
 
// 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,
        },
      ],
    }
  )
}
<head> output
<meta property="og:image" content="<generated>" />
<meta property="og:image:alt" content="About Acme" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />

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 } }) {
  // ...
}
RouteURLparams
app/shop/opengraph-image.js/shopundefined
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.

OptionType
altstring
size{ width: number; height: number }
contentTypestring - image MIME type

alt

opengraph-image.tsx | twitter-image.tsx
export const alt = 'My images alt text'
 
export default function Image() {}
<head> output
<meta property="og:image:alt" content="My images alt text" />

size

opengraph-image.tsx | twitter-image.tsx
export const size = { width: 1200, height: 630 }
 
export default function Image() {}
<head> output
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />

contentType

opengraph-image.tsx | twitter-image.tsx
export const contentType = 'image/png'
 
export default function Image() {}
<head> output
<meta property="og:image:type" content="image/png" />

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.

OptionTypeDefault
dynamic'auto' | 'force-dynamic' | 'error' | 'force-static''auto'
revalidatefalse | 'force-cache' | 0 | numberfalse
runtime'nodejs' | 'edge''nodejs'
preferredRegion'auto' | 'global' | 'home' | string | string[]'auto'
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/og'
 
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

VersionChanges
v13.3.0opengraph-image and twitter-image introduced.