·5 min read

Astro Open Graph Images: The Easy Way (No Build Step)

Add beautiful Open Graph images to your Astro site in under 2 minutes. No Satori, no Puppeteer, no build scripts — just a URL in your frontmatter.

Adding Open Graph images to an Astro site is surprisingly annoying. Most guides tell you to set up Satori, write JSX templates, configure fonts, handle build-time generation, and debug edge cases. For something that should take 2 minutes, you end up spending an afternoon.

There's a much easier way: use a URL-based API that generates the image on demand. No build step, no dependencies, no maintenance. Here's how.

The problem with self-hosted OG images in Astro

The typical Astro OG image setup involves one or more of these:

All of these add complexity to your build pipeline, increase build times, and require ongoing maintenance. And if you want to change the design later? You're editing JSX templates and rebuilding everything.

The easy way: URL-based OG images

Instead of generating images at build time, you can use a URL that returns an image on demand. Drop it in your Astro layout's <meta> tags and you're done.

Here's how it works with OGMagic:

Step 1: Add the meta tag to your layout

---
// src/layouts/BaseLayout.astro
const { title, description } = Astro.props;
const domain = new URL(Astro.site || "https://yoursite.com").hostname;

const ogImage = `https://ogmagic.dev/api/og?${new URLSearchParams({
  template: "gradient-mesh",
  title,
  description: description || "",
  domain,
})}`;
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>{title}</title>
    <meta name="description" content={description} />

    <!-- Open Graph -->
    <meta property="og:title" content={title} />
    <meta property="og:description" content={description} />
    <meta property="og:image" content={ogImage} />
    <meta property="og:image:width" content="1200" />
    <meta property="og:image:height" content="630" />

    <!-- Twitter Card -->
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content={title} />
    <meta name="twitter:image" content={ogImage} />
  </head>
  <body>
    <slot />
  </body>
</html>

That's it. Every page that uses this layout now has a dynamic OG image with the page title, description, and your domain. No build step, no dependencies.

Step 2: Use it in your pages

---
// src/pages/index.astro
import BaseLayout from "../layouts/BaseLayout.astro";
---

<BaseLayout
  title="My Awesome Site"
  description="Building cool stuff with Astro"
>
  <h1>Welcome!</h1>
</BaseLayout>

Step 3: Blog posts with dynamic images

For content collections (Astro's blog setup), each post automatically gets a unique OG image:

---
// src/pages/blog/[...slug].astro
import { getCollection } from "astro:content";
import BaseLayout from "../../layouts/BaseLayout.astro";

export async function getStaticPaths() {
  const posts = await getCollection("blog");
  return posts.map((post) => ({
    params: { slug: post.slug },
    props: { post },
  }));
}

const { post } = Astro.props;
const { Content } = await post.render();
---

<BaseLayout
  title={post.data.title}
  description={post.data.description}
>
  <article>
    <h1>{post.data.title}</h1>
    <Content />
  </article>
</BaseLayout>

Every blog post now has a beautifully styled OG image — no per-post configuration needed. The image is generated from the title and description you already have in your frontmatter.

Choosing a template

OGMagic has 55+ templates to choose from. The free tier includes 5 templates (gradient-mesh, minimal-dark, split-card, bold-statement, sunrise). Pro ($12 one-time) unlocks all of them.

You can preview templates in the visual editor and switch between them by changing the template parameter — no code changes needed.

// Switch template by changing one parameter
const ogImage = `https://ogmagic.dev/api/og?template=tokyo-night&title=${title}`;
// or
const ogImage = `https://ogmagic.dev/api/og?template=nord&title=${title}`;

Custom images per page type

Want different styles for different sections? Use different templates:

---
// Different templates for different content types
const templates = {
  blog: "minimal-dark",
  docs: "blueprint",
  changelog: "retro-terminal",
};

const ogImage = `https://ogmagic.dev/api/og?${new URLSearchParams({
  template: templates[section] || "gradient-mesh",
  title,
  description: description || "",
  domain,
})}`;
---

Custom accent colors (Pro)

With Pro, you can override template accent colors to match your brand:

const ogImage = `https://ogmagic.dev/api/og?${new URLSearchParams({
  template: "gradient-mesh",
  title: "My Brand Post",
  accent: "#ff6b35",  // Your brand color
  domain: "mybrand.com",
})}`;

How this compares to other approaches

ApproachSetup timeBuild impactMaintenanceTemplates
OGMagic (URL API)2 minNoneNone55+
astro-og-canvas30 minAdds build timeMediumLimited
Satori + resvg1-2 hoursAdds build timeHighDIY
Puppeteer2-4 hoursHeavy (headless browser)HighDIY

Performance and caching

OGMagic runs on edge infrastructure with response times under 200ms. Images are cached at the CDN level, so subsequent requests for the same parameters are served instantly. Social media crawlers (Facebook, Twitter, LinkedIn) only fetch OG images once and cache them on their end too.

Since the image is generated on demand (not at build time), your Astro build stays fast regardless of how many pages you have. A site with 1,000 blog posts doesn't need to generate 1,000 images during astro build.

Getting started for free

The free tier includes 50 API calls per month and 5 templates — no signup, no API key, no credit card. Just use the URL. That's enough for most personal blogs and small sites.

If you need more templates or higher limits, Pro is $12 one-time (not a subscription) for 5,000 calls/month and all 55+ templates.

Add OG images to your Astro site in 2 minutes

Pick a template, copy the URL, paste it in your layout. Done.

📬

Get OG tips & product updates

Join our newsletter for Open Graph best practices, new template releases, and exclusive discounts. No spam, unsubscribe anytime.

🔒 We respect your inbox. No spam, ever.