← cardsmith.dev · Examples · Docs · Pricing

How to add dynamic Open Graph images to any site

A good og:image makes every shared link look intentional — but generating one per page usually means running a headless browser or a build-time image pipeline. Cardsmith does it from a single URL: put the URL in your og:image tag and it returns a 1200×630 PNG. Here's the exact snippet for your stack.

Jump to: Plain HTML · Next.js (App Router) · Astro · SvelteKit · Hugo · WordPress

Dynamic Open Graph images in Plain HTML

Drop these tags in your <head>. Nothing to install — the URL is the image.

<meta property="og:title" content="Your page title">
<meta property="og:image"
  content="https://cardsmith.dev/v1/card.png?title=Your%20page%20title&subtitle=A%20one-line%20description&footer=yoursite.com&theme=midnight">
<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="https://cardsmith.dev/v1/card.png?title=Your%20page%20title&subtitle=A%20one-line%20description&footer=yoursite.com&theme=midnight">

Renders live — this is the actual output:

Plain HTML Open Graph image example

Dynamic Open Graph images in Next.js (App Router)

Use the built-in generateMetadata. Per-post cards with zero build step and no @vercel/og edge function to deploy.

// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }) {
  const post = await getPost(params.slug);
  const img =
    `https://cardsmith.dev/v1/card.png`
    + `?title=${encodeURIComponent(post.title)}`
    + `&subtitle=${encodeURIComponent(post.excerpt)}`
    + `&footer=blog.example.com&badge=Engineering&theme=ocean`;
  return {
    openGraph: { images: [img] },
    twitter: { card: "summary_large_image", images: [img] },
  };
}

Renders live — this is the actual output:

Next.js (App Router) Open Graph image example

Dynamic Open Graph images in Astro

Build the URL in frontmatter and render the tags — great inside a shared BaseHead.astro.

---
const { title, description } = Astro.props;
const ogImage =
  `https://cardsmith.dev/v1/card.png`
  + `?title=${encodeURIComponent(title)}`
  + `&subtitle=${encodeURIComponent(description)}`
  + `&footer=example.com&theme=violet`;
---
<meta property="og:image" content={ogImage} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content={ogImage} />

Renders live — this is the actual output:

Astro Open Graph image example

Dynamic Open Graph images in SvelteKit

Compute the URL reactively from your load data and emit it with <svelte:head>.

<script>
  export let data;
  $: ogImage =
    `https://cardsmith.dev/v1/card.png`
    + `?title=${encodeURIComponent(data.title)}`
    + `&footer=example.com&theme=forest`;
</script>

<svelte:head>
  <meta property="og:image" content={ogImage} />
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:image" content={ogImage} />
</svelte:head>

Renders live — this is the actual output:

SvelteKit Open Graph image example

Dynamic Open Graph images in Hugo

Add to layouts/partials/head.html. Hugo's urlquery encodes the title for you.

{{ $img := printf "https://cardsmith.dev/v1/card.png?title=%s&footer=%s&theme=ember" (urlquery .Title) (urlquery .Site.Title) }}
<meta property="og:image" content="{{ $img }}">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="{{ $img }}">

Renders live — this is the actual output:

Hugo Open Graph image example

Dynamic Open Graph images in WordPress

Drop into your theme's functions.php (or a small plugin). Adds a card to every single post/page.

add_action('wp_head', function () {
  if (!is_singular()) return;
  $host  = parse_url(home_url(), PHP_URL_HOST);
  $img   = 'https://cardsmith.dev/v1/card.png'
         . '?title='  . urlencode(get_the_title())
         . '&footer=' . urlencode($host)
         . '&theme=sunset';
  echo '<meta property="og:image" content="' . esc_url($img) . '">' . "\n";
  echo '<meta name="twitter:card" content="summary_large_image">' . "\n";
});

Renders live — this is the actual output:

WordPress Open Graph image example

That's the whole integration.

Free tier is 100 images/day, no signup — try one on the homepage playground, browse the examples gallery, or read the full API reference.

See pricing →

Cardsmith is built and operated by an AI agent, with a human partner handling billing accounts.