ThumbAPI logoThumbAPI

OG Image Generator for News Sites — One Call Per Headline

A news site publishing 20–200 stories a day cannot afford a designer per headline. But the story that ships to Facebook, LinkedIn, Slack, and Google Discover with no OG image — or the same generic house image on every article — loses roughly a third of the click-throughs its headline could have earned. This page is the working recipe: one POST per new article, a unique 1200×630 card written to your CDN, wired into og:image before the story is indexable.

If you want the spec sheet — 1200×630, safe area, aspect ratio, meta tag setup — the what an OG image actually is guide covers it in depth. This page is the newsroom-specific pipeline that assumes you already ship articles and just need OG cards attached to each one automatically.

Wire OG images into your publish pipeline in one afternoon

Get a Free API Key

The Problem

Newsroom CMS platforms (Arc XP, Brightspot, WordPress VIP, Ghost, headless setups on Sanity or Contentful) all ship articles the same way: an editor writes a headline, hits publish, the story appears on the homepage and the RSS feed. The OG image field is either blank, pulled from a default site-wide fallback, or filled with the story's lead photograph — which is usually cropped badly and lacks the headline text.

The three failure modes news publishers hit repeatedly:

  • No image at all. Article goes viral inside a Slack workspace, the preview shows a title with no visual anchor, CTR craters.
  • The same house image on every story. Trained eyes scroll past. Repeated visual = zero information about the article.
  • Lead photograph, cropped to 1.91:1. A vertical portrait becomes a decapitated forehead. A wide landscape becomes an unreadable letterbox with no context.

The Workflow

A single publish-time hook covers every article going forward. No editor changes their workflow, no designer touches the pipeline.

  1. Trigger. Editor hits publish. CMS fires apost.published webhook (or a database trigger, or a server action in a headless setup).
  2. Extract the headline. Pull the article title (and optionally the section slug, e.g. politics, tech, sports) from the payload.
  3. Call ThumbAPI. POST the title and format: "blogpost" to https://api.thumbapi.dev/v1/generate. Optional: category: "news" to bias the design toward news-style typography.
  4. Push the response to your CDN. Decode the base64 payload, upload to S3, R2, or Fastly, and get back an absolute URL.
  5. Write the URL back. Store the CDN URL on the article record. Your template already renders og:image from that field.

End result: by the time the article surfaces on the site, in the RSS feed, or on a syndication partner, the OG image is live at an absolute URL. Social scrapers pick it up on the first fetch.

Code Example — Publish Webhook (Node.js)

The reference implementation below sits behind a WordPress, Ghost, or headless-CMS webhook. It receives a JSON payload, generates the image, uploads to S3, and PATCHes the article back with the OG URL. Swap the S3 client for R2, Bunny, or any object store — the shape is identical.

news-og-webhook.mjs
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

const s3 = new S3Client({ region: "us-east-1" });
const BUCKET = "cdn.example-news.com";

export async function handler(req) {
  const { id, title, section, slug } = await req.json();

  const res = await fetch("https://api.thumbapi.dev/v1/generate", {
    method: "POST",
    headers: {
      "x-api-key": process.env.THUMBAPI_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      title,
      format: "blogpost",
      category: "news",
      outputFormat: "png",
      useLogo: true, // uses your saved masthead logo asset
    }),
  });

  if (!res.ok) throw new Error(`ThumbAPI ${res.status}: ${await res.text()}`);
  const { image } = await res.json();
  const base64 = image.startsWith("data:") ? image.split(",", 2)[1] : image;
  const png = Buffer.from(base64, "base64");

  const key = `og/${section}/${slug}.png`;
  await s3.send(new PutObjectCommand({
    Bucket: BUCKET,
    Key: key,
    Body: png,
    ContentType: "image/png",
    CacheControl: "public, max-age=31536000, immutable",
  }));

  const ogUrl = `https://cdn.example-news.com/${key}`;

  // PATCH your CMS — this shape is CMS-specific
  await fetch(`${process.env.CMS_URL}/articles/${id}`, {
    method: "PATCH",
    headers: {
      Authorization: `Bearer ${process.env.CMS_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ og_image: ogUrl }),
  });

  return new Response(JSON.stringify({ ok: true, ogUrl }));
}

Deploy the handler to Vercel Functions, AWS Lambda, or Cloudflare Workers — the request stays under the default 60-second timeout. For newsrooms above ~500 articles/day, run the generate call in a queue (SQS, Cloud Tasks, or a lightweight worker) so bursts during breaking news don't back up the publish path.

Headline Safe Area — What News-Style OG Images Need

News OG cards render differently from generic blog covers because headlines are longer, denser, and often laden with punctuation. Two practical rules:

  • Keep critical text in the middle 80% of the frame. Discord and older iMessage renderers crop the outer 10%. A subhead shoved to the edge disappears.
  • Two to four bold words is the target scale. A 70-character headline works as a title but not as visual text on a 400px preview. The AI trims and picks the punchiest phrase — you can pass the full headline in title.

The category: "news" hint biases layout toward editorial typography — condensed sans-serif, higher contrast, less gradient — so cards read as journalism rather than marketing.

Customization Parameters That Matter for Newsrooms

ParameterWhat it does for a news site
formatblogpost gives you the 1200×630 OG standard. Also x for a dedicated Twitter/X card if you want a different crop for that platform.
categorynews biases toward editorial typography. Usetech, finance, or lifestyle per section if your CMS carries the taxonomy.
useLogoOverlays your masthead. Upload once as a saved Logo asset, then pass true per request. Every card carries your brand.
customAssetsIdPro/Business feature. Upload 3–6 reference cards from your masthead and every OG image inherits that visual style — typography, palette, layout tendencies.
outputFormatpng is safest for older syndication crawlers. webp is ~40% smaller and works on all modern platforms.

Cost at Newsroom Scale

A standard OG image on the blogpost format costs 10 credits. Because the image is generated once per article and cached on your CDN, you pay per article — not per share or per pageview.

  • 1,000 articles/month — 10,000 credits. Covered by the Business plan ($199/mo).
  • 10,000 articles/month — 100,000 credits. Talk to us for a volume plan.
  • 100,000 articles/month (wire-service scale) — custom pricing with dedicated infrastructure.

For a regional daily publishing 30 stories a day (~900/month), the Business plan gives you 10× headroom for breaking-news spikes.

Related Newsroom Automations

OG image generation is one piece of a modern editorial stack. Two common companions:

  • Homepage rail cards. Same generate call, different format — request format: "x" or a square crop for section rails and email newsletters.
  • Author photo overlay. Set usePhoto: true per byline and pass a base64 headshot on the request. Useful for opinion columns and personality-driven sections.

FAQ

Does this work with WordPress VIP / Arc XP / Brightspot?

Yes — all three fire a publish webhook you can subscribe to. The handler shape above is portable. For WordPress there's also a ThumbAPI WordPress integration that hooks the publish action directly if you don't want a separate webhook service.

What about breaking news where the headline changes 3–4 times?

Regenerate on the post.updated event with the same slug, overwrite the S3 object, and invalidate the CDN key. Because the OG URL is stable, social platforms re-fetch on their next scrape.

Can I match my masthead's visual style?

Yes. Upload 3–6 reference cards as a custom reference set on the Pro or Business plan and pass its ID via customAssetsId. Every card inherits your typography and palette without a template stage.

How do we handle wire-service articles we didn't write?

Same pipeline — the webhook fires on any publish, wire content included. If licensing requires the original outlet's image, skip the generation step for that section. Most newsrooms only generate for their own byline content anyway.

Is there a free tier to test this against real headlines?

Yes. The free tieris 50 credits per month — enough to generate 5 OG cards from your last week of headlines and run them through Facebook's Sharing Debugger before you wire up the webhook.

Ship a unique OG card with every story your newsroom publishes

Start Free