# OG images in Astro

`<OgImage>` in the head, every URL signed during the build.

## Where it plugs in

The integration signs each image URL while Astro builds, without a single request to the API — a collection of a thousand posts builds as fast as an empty one. Each image is rendered on the first crawler hit and cached after that.

`src/pages/blog/[...slug].astro`

```astro
---
// npm i @shareglint/astro
// astro.config.mjs: integrations: [shareglint()] - reads SHAREGLINT_ACCOUNT_ID
// and SHAREGLINT_SIGNING_SECRET; every URL is signed during the build.
import { getCollection } from 'astro:content';
import OgImage from '@shareglint/astro/OgImage.astro';
import Layout from '../../layouts/Base.astro';

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

const { post } = Astro.props;
---

<Layout title={post.data.title}>
  <OgImage
    slot="head"
    template="blog-og"
    fields={{
      title: post.data.title,
      author: post.data.author,
      date: post.data.pubDate.toISOString().slice(0, 10),
      site: 'yourblog.com',
    }}
  />
  <slot />
</Layout>
```

## The trap

Astro does not put `.env` into `process.env` while it reads `astro.config.mjs`. Export the variables in the shell or in CI, or pass them through `loadEnv` — otherwise the build warns and `<OgImage>` has no account to sign for.

## What it costs

A hundred images a month free, then $9 for two thousand. The same post rendered twice returns the existing URL and uses no quota — so rebuilding your site costs nothing.
