v5.70.0 15 June 2026 Improvement

Open Graph Images — 279 Pages, Build-Time Generation, Gated Deployment

Why This Matters

API documentation gets shared. A link to an endpoint page dropped in Slack, a guide shared on LinkedIn, a Stack Overflow answer pointing at the webhooks reference — all of them render a preview card. Without og:image, that card is a blank rectangle with a URL. With it, the SpeyBooks brand and the specific page content appear in the preview.

More than branding, this closes the last significant SEO gap on docs.speybooks.com. The July audit flagged og:image missing on all 280 pages as the only incomplete OG tag coverage. It is now complete, and the G4 gate in the deploy pipeline asserts it stays that way.


Open Graph Image Generation

Build-time generation with Satori and Sharp

279 OG cards generated at build time — one per page — before astro build runs. Cards are written to public/og/ and baked into dist/ by Astro’s static file handling automatically.

  • Card design Dark theme matching the SpeyDocs UI (#0f172a background, #e2e8f0 text, #2563eb accent). SpeyBooks logo top-left, section badge top-right, title centre, description below, docs.speybooks.com and the “Accounting as Code · UK Developer API” tagline in the footer. A 4px accent bar runs the full left edge.

  • Page-kind differentiation Endpoint pages carry a coloured method badge (GET/POST/PUT/PATCH/DELETE, matching the CSS variables) and the API path in monospace beneath it. Resource landing pages carry the tag description as the subtitle. Schema pages carry a generic schema description. Guide and preamble pages carry the page description from the IR.

  • Content-addressed cache Cards are cached in .og-cache/ by SHA-256 hash of their inputs (title, description, section, method, path) plus a TEMPLATE_VERSION string. Identical inputs reuse the cached PNG with no Satori call. On the first run all 279 generated in under 30 seconds; subsequent runs complete in under 3 seconds from cache.

  • Font handling Satori does not support WOFF2 or variable fonts. Inter Regular and Bold are fetched as static-weight WOFF from Google Fonts on the first build and cached to public/fonts/. Subsequent builds load from disk with no network call.

Meta tags

Five tags added to Layout.astro for all pages:

og:image          https://docs.speybooks.com/og/{slug}.png
og:image:width    1200
og:image:height   630
twitter:card      summary_large_image
twitter:image     https://docs.speybooks.com/og/{slug}.png

Slug derived from the page route using the same replace logic as the generator (/api/v1/accounts/api--v1--accounts.png), so route and image are always in sync.


Deploy Pipeline

G4 assertion extended

The existing G4 gate (281 pages; 202 endpoint pages match spec; 18 schemas) now also asserts 279 OG images. A deploy that fails to generate OG images fails G4 and does not proceed to the live swap.

OG phase added

A dedicated OG phase runs between G2 (parser verification) and G3 (Astro build). Output is logged with a count and timing. On cache-hit runs the phase completes in 2 seconds.


SEO Fixes

Legacy redirect for pre-refactor guide URLs

AhrefsBot was returning 404 on /guides/dividends and /guides/csv-import — URLs from before the /api/ prefix was added during the SpeyDocs refactor. A pattern redirect added to nginx:

location ~ ^/guides/(.*)$ {
    return 301 /api/guides/$1;
}

Single hop, no chain. Verified with curl before reload.


Operational Impact

  • 279 pages now carry correct og:image, og:image:width, og:image:height, twitter:card, and twitter:image tags — 0 before this release.
  • OG coverage verified at opengraph.xyz: 12/12 meta tags passing, correct preview card rendering.
  • Build time addition: under 3 seconds on cache-hit runs; under 30 seconds on full regeneration.
  • G4 gate extended — OG image count is now a deploy-blocking assertion.
  • Two legacy guide URLs now return 301 instead of 404.

Files Changed

Backend: None.

Docs site:

  • scripts/generate-og-images.ts — new; Satori + Sharp build-time generator
  • src/lib/og-cache.ts — new; content-addressed cache (ported from speytech.com)
  • src/layouts/Layout.astroog:image, og:image:width/height, twitter:card, twitter:image added
  • deploy.sh — OG phase added; G4 assertion extended to include OG image count
  • public/fonts/Inter-Regular.woff — new; cached from Google Fonts, required by Satori
  • public/fonts/Inter-Bold.woff — new; cached from Google Fonts, required by Satori
  • package.json / pnpm-lock.yamlsatori, @resvg/resvg-js, sharp, tsx added as dev dependencies
  • .gitignorepublic/og/ excluded (generated at build time, not committed)

nginx (docs.speybooks.com):

  • Legacy /guides/*/api/guides/* redirect pattern added

OG image coverage completes the open meta-tag audit from the June 2026 SEO review. The next docs pass addresses the five pages with missing <h1> tags in the SpeyDocs template.