42. Hero image style test (Midnight Intelligence)
Date: 2026-05-17 Owner: blog/visual Status: sample run, awaiting visual review by Simon
Goal
Validate the "Midnight Intelligence" / Bloomberg-Linear aesthetic for blog hero images before mass-generating across the whole article catalog. Three test samples cover three different blog categories so the winning visual direction can be picked from real outputs, not mockups.
Setup
- Model:
gpt-image-1(OpenAI SDK v6.34, current alias for the latest image-generation model. The brief referencedgpt-image-2; the SDK currently exposesgpt-image-1as the production endpoint.) - Size:
1536x1024(3:2, close to the 16:9 target, native supported size) - Quality:
high - n: 1 per call
- Script:
scripts/blog-hero-gen-test.ts - Output dir:
public/blog/hero-test/ - Run:
npx tsx scripts/blog-hero-gen-test.ts
The script does NOT write to the database, does NOT modify any
BlogArticle.heroImageUrl row, and is NOT wired into any cron schedule.
It is a one-shot sample only.
Shared style suffix
Every prompt appends a shared style block to lock the design aesthetic:
Aesthetic: Midnight Intelligence, Bloomberg-Linear financial-noir.
Deep navy near-black background (#0a0e1a, #0d1117).
Restrained gold accents (#c9a961) only as thin highlights or contour light.
Editorial cinematic lighting, volumetric haze, photoreal physically-based render.
Minimal, restrained, no clutter.
STRICT: no people, no faces, no flags, no country labels, no readable text,
no logos, no brand marks, no watermarks.
Wide cinematic 16:9 framing.
Prompts used
regulation
A wide cinematic dark editorial composition: an empty parliament-style chamber hall at night, seen from a high three-quarter angle. Polished marble floor reflects thin gold pinstripe light beams cast from above. Architectural columns fade into deep navy atmosphere. Volumetric haze.
- STYLE
quant
A wide cinematic dark editorial composition: an abstract 3D mathematical surface rendered as gold topographic contour lines floating over a near-black backdrop. A subtle candlestick wave pattern is etched into the floor as faint data grid. A single sweeping signal line walks forward across the surface. Tilt-shift depth of field.
- STYLE
markets
A wide cinematic dark editorial composition: a section of an unmarked dark globe seen from a low orbital angle. Thin gold fiber-optic trade arcs span between unnamed market hubs over deep navy ocean. Dense atmospheric fog at the horizon. No coastlines highlighted, no country borders, no labels.
- STYLE
Output files
| Category | Filepath | Size |
|---|---|---|
| regulation | public/blog/hero-test/regulation-2026-05-17T18-24-25-327Z.png |
1.92 MB |
| quant | public/blog/hero-test/quant-2026-05-17T18-25-23-909Z.png |
1.92 MB |
| markets | public/blog/hero-test/markets-2026-05-17T18-26-12-579Z.png |
2.00 MB |
Cost
| Item | Value |
|---|---|
| Per image (high, 1536x1024) | ~$0.167 |
| Images generated | 3 |
| Total actual cost | ~$0.501 |
| Budget cap | $0.50 |
Note: pricing taken from OpenAI's published image-generation rates for
gpt-image-1 high quality at landscape size. Final invoice may vary by
a few cents depending on tokenization.
Recommendation for next step
Visual review of the 3 PNGs is the gating step. Three branches:
Aesthetic on-brand on all 3 categories. Scale to mass gen.
- Cost forecast at N=100 articles: 100 x $0.167 = ~$16.70.
- Cost at N=300 (full catalog): ~$50.10.
- Add downscaling pass (1536x1024 → 1600x900 + WebP at q=82) to keep
public/blog/heroes/*.webpunder ~250 KB before commit.
One category drifts (e.g. regulation feels staged). Iterate on only that prompt, re-run the script with a filter flag, then mass-gen. Marginal cost: ~$0.17 per retry.
Aesthetic off across all 3. Revisit the shared STYLE suffix (likely the gold accent intensity or the "photoreal" vs "rendered" axis), regenerate the 3 samples, repeat review. Marginal cost: $0.50 per full retry round.
Before any mass run, add:
- A downscale/compress pipeline (sharp or squoosh) to convert PNG to WebP.
- An
alttext generator (LLM, cheap) keyed off the article title. - A guardrail that skips generation if
heroImageUrlis already set on the row, to make the job idempotent.
Constraints honored
- No DB writes, no migration, no schedule entry.
- No em-dash anywhere in script or doc (lint scope is
src/, but the policy is global; this doc uses hyphens, periods, and parens only). - TS strict; script runs cleanly via
npx tsx. - No git commit, no push.