The real magic of Vercel’s OG Image Generation is that it’s not really about generating images at all, it’s about generating HTML that browsers then render into images.

Here’s a blog post page on a Vercel site. When you share this link on social media, the platform (like Twitter or Discord) fetches a special URL to get an image preview. Vercel’s OG Image Generation handles this by serving a dynamically generated HTML page, which looks like this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Awesome Blog Post</title>
    <meta property="og:title" content="My Awesome Blog Post">
    <meta property="og:description" content="A deep dive into the intricacies of web development.">
    <meta property="og:image" content="https://your-site.com/_next/image?url=%2Fapi%2Fog%2Fposts%2Fmy-awesome-blog-post&w=1920&q=75">
    <style>
        body {
            font-family: sans-serif;
            background-color: #f0f4f8;
            margin: 0;
            padding: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
            height: 100vh;
            box-sizing: border-box;
        }
        .container {
            background-color: #ffffff;
            border-radius: 16px;
            padding: 40px;
            box-shadow: 0 10px 25px rgba(0,0,0,0.1);
            display: flex;
            align-items: center;
        }
        .text-content {
            margin-left: 40px;
        }
        h1 {
            color: #1a202c;
            font-size: 48px;
            margin-bottom: 16px;
        }
        p {
            color: #4a5568;
            font-size: 24px;
        }
    </style>
</head>
<body>
    <div class="container">
        <img src="/images/blog-thumbnail.png" alt="Blog Post Thumbnail" width="200" height="200" style="border-radius: 8px;">
        <div class="text-content">
            <h1>My Awesome Blog Post</h1>
            <p>A deep dive into the intricacies of web development.</p>
        </div>
    </div>
</body>
</html>

This HTML is served by a Vercel Serverless Function, typically defined in pages/api/og/[slug].js (or similar for App Router). When Vercel receives a request to a URL like https://your-site.com/api/og/posts/my-awesome-blog-post, it executes this function. The function dynamically fetches the necessary data for "My Awesome Blog Post" (title, description, perhaps an image URL) and then renders this HTML template. The og:image meta tag in the page’s <head> (which points to a Vercel Image Optimization URL) is what social media crawlers ultimately see and use. The Vercel Image Optimization service then takes that HTML, renders it into a PNG or JPEG, and serves it.

This approach solves the problem of static, pre-generated social media images. Before this, you’d either have to:

  1. Manually generate and upload an image for every single post.
  2. Use a third-party service that might be slow or costly.
  3. Build your own image generation service.

Vercel’s solution integrates directly into your Next.js or React project. You define an API route that returns the HTML, and Vercel handles the rest, including caching and optimization.

The core idea is that the og:image meta tag in your actual page’s <head> is not a direct image URL, but rather a URL that Vercel’s Image Optimization API knows how to handle. This URL, like /_next/image?url=%2Fapi%2Fog%2Fposts%2Fmy-awesome-blog-post&w=1920&q=75, tells Vercel’s optimizer to fetch the content at /api/og/posts/my-awesome-blog-post (which is your serverless function returning HTML), render that HTML, and then serve the resulting image.

The parameters w=1920 and q=75 are standard Vercel Image Optimization parameters for width and quality. The crucial part is url=%2Fapi%2Fog%2Fposts%2Fmy-awesome-blog-post, which encodes the path to your dynamic OG image generation function.

The most surprising thing most developers don’t realize is that the og:image tag on your public-facing page (e.g., <meta property="og:image" content="https://your-site.com/_next/image?url=%2Fapi%2Fog%2Fposts%2Fmy-awesome-blog-post&w=1920&q=75">) is not the direct image source for social media. It’s a pointer. Social media crawlers see this URL, request it, and Vercel’s image optimization service intercepts it. This service then fetches the HTML content pointed to by the url parameter (/api/og/posts/my-awesome-blog-post), renders that HTML into an image, and returns that image to the crawler. Your actual page’s og:image tag is essentially a Vercel-specific URL that triggers a serverless function to generate an HTML page, which is then rendered as an image.

The next step you’ll encounter is handling more complex layouts and dynamic data fetching within your OG image generation function.

Want structured learning?

Take the full Vercel course →