Use when: generating social media and preview assets for an artwork (og-image, poster-frame, loop videos) using the deterministic render pipeline.
Generate deterministic, curated media assets from a browser-based generative artwork for use in social media embedding, gallery previews, and promotional channels.
docs/works/<slug>.js and has been tested.docs/app.js exposing window.__GENART_CAPTURE__).npm install and npx playwright install chromium have been run.node -e "import('playwright').then(() => console.log('ok')).catch(() => process.exit(1))"docs/work/<slug>/index.html (or equivalent route support is present)./work/<slug>/ loads shell runtime and artwork without 404.render-specs/<slug>.json with:
slug, title, categorytargetAssets (which formats to generate: og-image, poster-frame, loop-landscape, etc.)seedStrategy (random-range or fixed-list)variants (resolution, fps, format for each asset type)heroFrameHints (which animation frames are interesting for poster/og)validationNotes (checklist for author review)node scripts/render-pipeline.mjs prepare <slug>
Generates:
docs/media/<slug>/candidates/manifest.json — list of all candidate combinations (seeds × times × frames)docs/media/<slug>/validation-log.md — author checklist templateBest Practice: Review the manifest to ensure asset targets, seed ranges, and time candidates match your vision. If adjustments needed, update render-specs/<slug>.json and re-run prepare.
Run capture for each asset type needed:
node scripts/render-capture.mjs <slug> --asset og-image --limit 1
node scripts/render-capture.mjs <slug> --asset poster-frame --limit 1
node scripts/render-capture.mjs <slug> --asset loop-landscape --limit 1
node scripts/render-capture.mjs <slug> --asset loop-vertical --limit 1 # if needed
node scripts/render-capture.mjs <slug> --asset loop-square --limit 1 # if needed
Best Practice: Start with --limit 1 to test capture works. If quality issues occur:
--limit 5 to generate multiple seed/time/frame variantsdocs/media/<slug>/candidates/renders/Outputs:
docs/media/<slug>/candidates/renders/<candidate-id>.png or .mp4docs/media/<slug>/candidates/frames/<candidate-id>/ (frame sequences for video)docs/media/<slug>/candidates/reports/<timestamp>.json (capture metadata)Key parameters on capture URLs:
width, height — canvas resolutionseed — deterministic randomnesstime — fixed render timestamp (for clocks/time-based art)frame — still image frame time (0–duration in seconds)duration — video loop lengthui=0 — hide UI chromefullscreen=1 — fullscreen layoutdocs/media/<slug>/validation-log.md in editor.docs/media/<slug>/candidates/renders/.## og-image
- [x] Best candidate selected
- [x] Readable at thumbnail scale
- [x] No artifacts
- [x] Approved candidate id: og-image--seed-123456--time-2026-04-08T12-00-00-000Z--frame-0-5
Best Practice:
Once approved candidate IDs are documented, finalize:
node scripts/render-pipeline.mjs finalize <slug> \
--og docs/media/<slug>/candidates/renders/og-image--seed-123456--time-2026-04-08T12-00-00-000Z--frame-0-5.png \
--poster docs/media/<slug>/candidates/renders/poster-frame--seed-123456--time-2026-04-08T12-00-00-000Z--frame-0-5.png \
--landscape docs/media/<slug>/candidates/renders/loop-landscape--seed-123456--time-2026-04-08T12-00-00-000Z--dur-4.mp4 \
--vertical docs/media/<slug>/candidates/renders/loop-vertical--seed-123456--time-2026-04-08T12-00-00-000Z--dur-4.mp4 \
--square docs/media/<slug>/candidates/renders/loop-square--seed-123456--time-2026-04-08T12-00-00-000Z--dur-4.mp4
Outputs:
docs/media/<slug>/og-image.png (1200×630)docs/media/<slug>/poster-frame.png (1920×1080)docs/media/<slug>/loop-landscape.mp4 (1280×720, 3–6s loop)docs/media/<slug>/loop-vertical.mp4 (1080×1920, optional)docs/media/<slug>/loop-square.mp4 (1080×1080, optional)docs/media/<slug>/metadata.json (asset reference record)Note: Omit --vertical or --square if those formats were not part of target assets or failed validation.
Once finalized, assets are ready for:
og:image, og:video metadata (future: auto-inject from metadata.json)./all/ index (future enhancement).og-image.png as preview.# 1. Prepare
node scripts/render-pipeline.mjs prepare masked-time-dots
# 2. Capture all asset types
node scripts/render-capture.mjs masked-time-dots --asset og-image --limit 1
node scripts/render-capture.mjs masked-time-dots --asset poster-frame --limit 1
node scripts/render-capture.mjs masked-time-dots --asset loop-landscape --limit 1
node scripts/render-capture.mjs masked-time-dots --asset loop-square --limit 1
# 3. Validate in editor
# Edit: docs/media/masked-time-dots/validation-log.md
# Review: docs/media/masked-time-dots/candidates/renders/
# 4. Finalize
node scripts/render-pipeline.mjs finalize masked-time-dots \
--og "docs/media/masked-time-dots/candidates/renders/og-image--seed-200000--time-2026-04-08T08-08-08-000Z--frame-0-5.png" \
--poster "docs/media/masked-time-dots/candidates/renders/poster-frame--seed-200000--time-2026-04-08T08-08-08-000Z--frame-0-5.png" \
--landscape "docs/media/masked-time-dots/candidates/renders/loop-landscape--seed-200000--time-2026-04-08T08-08-08-000Z--dur-4.mp4" \
--square "docs/media/masked-time-dots/candidates/renders/loop-square--seed-200000--time-2026-04-08T08-08-08-000Z--dur-4.mp4"
# Result: docs/media/masked-time-dots/{og-image.png, poster-frame.png, loop-landscape.mp4, loop-square.mp4, metadata.json}
window.__GENART_CAPTURE__ setup).docs/app.js and sets window.__GENART_CAPTURE__.ready after work load.window.__GENART_CAPTURE__ implements captureStill(frameTime) and (optionally) resetScene()./work/<slug>/ route exists and maps to shell page.npm install in repo root.npx playwright install chromium.--limit 1 to confirm environment is healthy.docs/work/<slug>/index.html.captureUrl points to /work/<slug>/... and not a missing path.--limit to sample more seeds and pick best.ffmpeg -version).Manifest prepared
docs/media/<slug>/candidates/manifest.json
docs/media/<slug>/validation-log.md
Candidates captured
og-image.png, poster-frame.png, loop-landscape.mp4, ...
Assets finalized
docs/media/<slug>/og-image.png
docs/media/<slug>/poster-frame.png
docs/media/<slug>/loop-landscape.mp4
docs/media/<slug>/metadata.json
All target assets exist in docs/media/<slug>/ with proper filenames:
og-image.pngposter-frame.pngloop-landscape.mp4loop-vertical.mp4 (if targeted)loop-square.mp4 (if targeted)metadata.jsonAssets are ready for SEO integration, gallery indexing, and social distribution.