OG Images in Next.js — Integration Guide
Add dynamic Open Graph images to your Next.js app in under 5 minutes. Works with App Router and Pages Router.
Install the SDK
Section titled “Install the SDK”npm install @atypical-consulting/og-engine-sdkApp Router — Route Handler
Section titled “App Router — Route Handler”Create app/api/og/route.ts:
import { OGEngine } from '@atypical-consulting/og-engine-sdk'
const og = new OGEngine(process.env.OG_ENGINE_KEY!)
export async function GET(request: Request) { const { searchParams } = new URL(request.url) const title = searchParams.get('title') ?? 'My Site' const description = searchParams.get('description') ?? ''
const image = await og.render({ format: 'og', title, description, style: { accent: '#38ef7d', font: 'Outfit', layout: 'left', }, })
return new Response(image, { headers: { 'Content-Type': 'image/png', 'Cache-Control': 'public, max-age=86400, s-maxage=86400', }, })}Add the Meta Tag
Section titled “Add the Meta Tag”In your layout or page:
export async function generateMetadata({ params }: Props): Promise<Metadata> { const post = await getPost(params.slug)
return { title: post.title, description: post.excerpt, openGraph: { images: [ { url: `/api/og?title=${encodeURIComponent(post.title)}&description=${encodeURIComponent(post.excerpt)}`, width: 1200, height: 630, }, ], }, }}Validate Before Rendering
Section titled “Validate Before Rendering”Use /validate to check text fits before paying for a render:
const check = await og.validate({ format: 'og', title: post.title, description: post.excerpt,})
if (!check.fits) { // Truncate or adjust text}Environment Setup
Section titled “Environment Setup”Add to .env.local:
OG_ENGINE_KEY=oge_sk_your_key_hereImportant: Only use the SDK in server-side code (Route Handlers, Server Components,
getServerSideProps). Never expose your API key to the browser.
Caching Strategy
Section titled “Caching Strategy”The route handler above sets a 24-hour cache. For static sites, consider generating images at build time:
import { OGEngine } from '@atypical-consulting/og-engine-sdk'import { writeFile } from 'fs/promises'
const og = new OGEngine(process.env.OG_ENGINE_KEY!)const posts = await getAllPosts()
for (const post of posts) { const image = await og.render({ format: 'og', title: post.title, description: post.excerpt, }) await writeFile(`public/og/${post.slug}.png`, image)}