How to Add Hosted Open Graph Images to Next.js
Create a hosted Open Graph image, save its public URL, and add it to Next.js App Router metadata or Pages Router Head tags.

The Problem with OG Images in Next.js
Every Next.js developer knows the pain: you build a beautiful blog or SaaS, share a link on Twitter, and… it looks terrible. No preview image, or worse — a generic placeholder. The problem is that generating dynamic Open Graph images for every page has traditionally been complex.
The common approaches — Puppeteer screenshots, @vercel/og with custom JSX, or manual Canva designs — all have drawbacks: slow builds, complex setup, or they just don't scale.
The API Approach: Zero Dependencies
Use an OG image API to create your image from a server or publishing workflow. Save the returned public URL with the post so serving your page needs no new render.
Your og:image meta tag points to a stored PNG. The private API key is used only when creating the image, and social crawlers never receive it.
Create the image before publishing
Get a key through email access and set OGMAGIC_API_KEY only in your server or build environment. Run this request when publishing content, then persist image.url with the post:
// Run on your server, at build time, or when publishing content.
const response = await fetch("https://www.ogmagic.dev/api/images", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.OGMAGIC_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ title: "My article", template: "gradient-mesh" }),
});
if (!response.ok) throw new Error("Image creation failed");
const image = await response.json();
// Save image.url with your content; use it in og:image and twitter:image.The examples below use a placeholder image URL. Replace it with the returned URL. Do not call the creation endpoint from browser code or publish your private key in metadata.
Next.js App Router
For a page with a saved image, export a metadata object from its server component:
// app/blog/my-article/page.tsx
import type { Metadata } from "next";
const imageUrl = "https://www.ogmagic.dev/images/11111111-1111-4111-8111-111111111111.png";
export const metadata: Metadata = {
title: "My article",
description: "What this article covers",
openGraph: {
title: "My article",
description: "What this article covers",
type: "article",
images: [{ url: imageUrl, width: 1200, height: 630, alt: "My article" }],
},
twitter: {
card: "summary_large_image",
title: "My article",
description: "What this article covers",
images: [imageUrl],
},
};
export default function ArticlePage() {
return <main><h1>My article</h1></main>;
}For a dynamic route, read the post's saved ogImage field in generateMetadata and use it in the same fields. With current App Router APIs, await params before reading the slug. Fetching existing content here avoids tying page delivery to a new image creation request. See the Next.js metadata reference.
Next.js Pages Router
With the Pages Router, render the saved URL using next/head:
// pages/my-article.tsx
import Head from "next/head";
const imageUrl = "https://www.ogmagic.dev/images/11111111-1111-4111-8111-111111111111.png";
export default function ArticlePage() {
return <>
<Head>
<title>My article</title>
<meta name="description" content="What this article covers" />
<meta property="og:title" content="My article" />
<meta property="og:description" content="What this article covers" />
<meta property="og:type" content="article" />
<meta property="og:image" content={imageUrl} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content={imageUrl} />
</Head>
<main><h1>My article</h1></main>
</>;
}Layout-Level OG Images
In the App Router, a root layout can export the same metadata shape for default previews. Nested openGraph objects replace the parent's object, so include the image alongside page-specific titles and descriptions. A more specific file-based opengraph-image can also take precedence; remove or update conflicting files when switching to hosted URLs.
Choosing Templates
OGMagic ships with 55+ templates optimized for different use cases: blog posts, SaaS products, documentation, and more. The free tier includes 5 templates — enough for most personal projects. Pro (€10 / US $12 one-time) unlocks everything.
Popular templates for Next.js blogs: minimal-dark, gradient-mesh, clean-white, vercel-style, and notion-style.
Browse all templates in the editor →
OGMagic vs @vercel/og
Vercel's built-in @vercel/og package is great, but it requires you to write JSX for your image layout, handle font loading, and debug rendering issues. OGMagic gives you:
- Hosted rendering: Send template options as JSON and reuse the returned image URL
- 55+ templates: Professional designs without CSS-in-JSX debugging
- Framework-agnostic: Same URL works in Next.js, Astro, Remix, or plain HTML
- HTTP integration: Use a server-side request without installing an image renderer
Testing Your OG Images
Check your published page with the Open Graph checker. Inspect the HTML and confirm both social image tags point to your saved public URL. Verify the image can load without authentication.
When a post changes, create the replacement image, save its new URL, and publish the updated metadata. Social platforms cache previews separately; use their inspection tools or test a fresh share after the change. Read the troubleshooting guide if a preview is missing.
Read the full API docs → or try the visual editor →
Add a saved OG image to your Next.js app
Email access; no password. Free tier includes 50 new images per 30 days.
The OGMagic newsletter
Get your 20% off Pro code
Join the OGMagic newsletter for a 20% discount code for Pro, Open Graph tips, and new templates.
Subscribe to OGMagic emails. Confirm by email; unsubscribe anytime.