Menu

#74 fix(og): make OG image generation network-independent

open
nobody
None
2026-05-15
2026-05-15
Anonymous
No

Originally created by: TheoV823

Problem

scripts/generate_og_images.py renders OG templates via a local HTTP server using Playwright, but the templates import Google Fonts over CDN. In headless environments where the CDN is unreachable (CI, offline, sandboxed), fonts silently fail to load and every image renders as a 1200×630 dark background with no text — ~10 KB instead of the expected 110–135 KB.

Discovered when attempting a full site OG refresh from main: all 41 renders came back at exactly 10,281 bytes. The run reported 44 saved, 0 failed (Playwright saw no exception — it just screenshotted a blank page). The bad renders were caught and discarded before commit, but only by manual size inspection.

Required fixes

1. Network-independent font loading

Replace the CDN @import in each og-*.html template with one of:

  • @font-face declarations pointing to local font files committed to the repo (e.g. site/fonts/)
  • Base64-encoded font data embedded in a shared CSS block
  • A shared <style> partial injected at render time by the script

The templates that need updating use Instrument Serif and DM Mono from fonts.googleapis.com.

2. Automatic blank-render detection

Add a post-screenshot validation step in the script:

MIN_VALID_BYTES = 30_000  # anything below this is almost certainly a blank render

stat = output_path.stat()
if stat.st_size < MIN_VALID_BYTES:
    output_path.unlink()  # don't keep the bad file
    print(f"INVALID {template}: render too small ({stat.st_size} bytes) — fonts may not have loaded")
    failed += 1
    continue

Adjust threshold based on the real minimum observed across valid renders (currently ~108 KB for the smallest legitimate image).

Before the final print("Done: ..."), open a quick montage or list of rendered images so a human can eyeball them before git add. Could be as simple as printing a summary table of filename + file size, or generating a lightweight HTML index page of all the rendered PNGs.

4. CI gate (stretch goal)

Add a CI check that runs the script in --dry-run / --validate mode and fails if any output would be below the size threshold.

Context

  • Script: scripts/generate_og_images.py
  • Templates: site/og-*.html (44 templates as of 2026-05-15)
  • Existing committed og.png files are intact and correct — this is a forward-only fix
  • No deployment needed until the fix lands and a clean re-render is confirmed valid

Discussion


Log in to post a comment.

Auth0 Logo