7 min read

Open Graph (OG) Image Generation

Learn how to optimize social media image generation through the Open Graph Protocol and @vercel/og library.
Table of Contents

To assist with generating dynamic Open Graph (OG) images, you can use the Vercel @vercel/og library to compute and generate social card images using Vercel Edge Functions.

  • Performance: With a small amount of code needed to generate images, functions can be started almost instantly. This allows the image generation process to be fast and recognized by tools like the Open Graph Debugger
  • Ease of use: You can define your images using HTML and CSS and the library will dynamically generate images from the markup
  • Cost-effectiveness: @vercel/og automatically adds the correct headers to cache computed images at the edge, helping reduce cost and recomputation
  • Basic CSS layouts including flexbox and absolute positioning
  • Custom fonts, text wrapping, centering, and nested images
  • Ability to download the subset characters of the font from Google Fonts
  • Compatible with any framework and application deployed on Vercel
  • View your OG image and other metadata before your deployment goes to production through the Open Graph tab

Vercel OG image generation is supported on both the Edge runtime and Node.js runtime.

In the Edge runtime, resources like fonts and images are loaded using the fetch method. This is effective for accessing local resources using the import.meta syntax. See using a local image for more information.

For the Node.js runtime, local resources can be loaded directly using fs.readFile. Alternatively, fetch can be used to load remote resources.

og.js
const fs = require('fs').promises;
 
const loadLocalImage = async () => {
  const imageData = await fs.readFile('/path/to/image.png');
  // Process image data
};

There are limitations when using vercel/og with the Next.js pages router and the Node.js runtime. Specifically, this combination does not support the return new Response(…) syntax. The table below provides a breakdown of the supported syntaxes for different configurations.

ConfigurationSupported SyntaxNotes
pages/ + Edge runtimereturn new Response(…)Fully supported.
app/ + Node.js runtimereturn new Response(…)Fully supported.
app/ + Edge runtimereturn new Response(…)Fully supported.
pages/ + Node.js runtimeNot supportedDoes not support return new Response(…) syntax with vercel/og.

It is recommended to use the Edge runtime with vercel/og to avoid this caveat.

  • Install Node.js 16 or newer by visiting nodejs.org
  • Install @vercel/og by running the following command inside your project directory:
pnpm
yarn
npm
pnpm i @vercel/og
  • For Next.js implementations, make sure you are using Next.js v12.2.3 or newer
  • Create API endpoints that you can call from your front-end to generate the images. Since the HTML code for generating the image is included as one of the parameters of the ImageResponse function, the use of .jsx or .tsx files is recommended as they are designed to handle this kind of syntax
  • It is recommended to use the Edge runtime by enabling the runtime: 'edge' config flag
  • To avoid the possibility of social media providers not being able to fetch your image, it is recommended to add your OG image API route(s) to Allow inside your robots.txt file. For example, if your OG image API route is /api/og/, you can add the following line:
    robots.txt
    Allow: /api/og/*
    If you are using Next.js, review robots.txt to learn how to add or generate a robots.txt file.

Get started with an example that generates an image from static text using Next.js by setting up a new app with the following command:

pnpm
yarn
npm
pnpm create next-app

Create an API endpoint by adding route.tsx under the app/api/og directory in the root of your project.

Then paste the following code:

Next.js (/app)
Next.js (/pages)
Other frameworks
app/api/og/route.tsx
import { ImageResponse } from 'next/og';
// App router includes @vercel/og.
// No need to install it.
 
export const runtime = 'edge';
 
export async function GET() {
  return new ImageResponse(
    (
      <div
        style={{
          fontSize: 40,
          color: 'black',
          background: 'white',
          width: '100%',
          height: '100%',
          padding: '50px 200px',
          textAlign: 'center',
          justifyContent: 'center',
          alignItems: 'center',
        }}
      >
        👋 Hello
      </div>
    ),
    {
      width: 1200,
      height: 630,
    },
  );
}

If you're not using a framework, you must either add "type": "module" to your package.json or change your JavaScript Functions' file extensions from .js to .mjs

Run the following command:

pnpm
yarn
npm
pnpm dev

Then, browse to http://localhost:3000/api/og. You will see the following image:

Deploy your project to obtain a publicly accessible path to the OG image API endpoint. You can find an example deployment at https://og-examples.vercel.sh/api/static.

Then, based on the Open Graph Protocol, create the web content for your social media post as follows:

  • Create a <meta> tag inside the <head> of the webpage
  • Add the property attribute with value og:image to the <meta> tag
  • Add the content attribute with value as the absolute path of the /api/og endpoint to the <meta> tag

With the example deployment at https://og-examples.vercel.sh/api/static, use the following code:

index.js
<head>
  <title>Hello world</title>
  <meta
    property="og:image"
    content="https://og-examples.vercel.sh/api/static"
  />
</head>

Every time you create a new social media post, you need to update the API endpoint with the new content. However, if you identify which parts of your ImageResponse will change for each post, you can then pass those values as parameters of the endpoint so that you can use the same endpoint for all your posts.

In the examples below, we explore using parameters and including other types of content with ImageResponse.

  • Recommended OG image size: 1200x630 pixels
  • @vercel/og uses Satori and Resvg to convert HTML and CSS into PNG
  • @vercel/og API reference
  • Only the Edge runtime is supported. The default Node.js runtime will not work. To use Node.js or any other runtime, you can use Satori directly. However, you will get better performance with @vercel/og and the Edge runtime
  • Only ttf, otf, and woff font formats are supported. To maximize the font parsing speed, ttf or otf are preferred over woff
  • Only flexbox (display: flex) and a subset of CSS properties are supported. Advanced layouts (display: grid) will not work. See Satori's documentation for more details on supported CSS properties
  • 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
Last updated on March 19, 2024