From 508ddf03ca9c8b8c0baae733d0daaddf91c4ba50 Mon Sep 17 00:00:00 2001 From: Ricardo Date: Mon, 9 Mar 2026 18:35:09 +0100 Subject: [PATCH] docs: document OG batch spawning architecture in CLAUDE.md Confab-Link: http://localhost:8080/sessions/edb1b7b0-da66-4486-bd9c-d1cfa7553b88 --- CLAUDE.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 531b500..367cfb6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -286,6 +286,21 @@ Page templates in the root directory: | `htmlmin` | Minifies HTML (build mode only, not watch mode) | | `eleventyImageTransformPlugin` | Optimizes `` tags | +#### Pre-Build Hook: OG Image Generation (`eleventy.before`) + +Generates OpenGraph images for posts without photos using Satori (Yoga WASM → SVG) + Resvg (Rust WASM → PNG). + +**Key files:** +- `lib/og.js` — generation logic, card layout, manifest-based caching +- `lib/og-cli.js` — CLI wrapper, accepts `batchSize` argument +- `eleventy.config.js` — spawns og-cli with batch loop + +**Architecture:** Runs as a separate process (`execFileSync`) to isolate WASM native memory from Eleventy. Uses **batch spawning** — each invocation generates up to 100 images, then exits with code 2 ("more remain"). The spawner re-loops until exit code 0. This keeps peak RSS at ~460 MB per batch regardless of total image count. + +**Why batch spawning:** Satori and Resvg allocate native memory outside V8's heap. `--max-old-space-size` only limits V8 — WASM native allocations are invisible to it. Without batching, 2,350+ images grow native memory to ~3 GB, OOM-killing the process in the 3 GB container. Batching fully releases native memory between invocations. + +**Caching:** Manifest at `.cache/og/manifest.json` maps slug → content hash. Only changed/new posts generate images. Manifest saved every 10 images for crash resilience. + #### Post-Build Hooks (`eleventy.after`) 1. **Pagefind indexing** — indexes all HTML files for search