Prompt file imported from mmarko88/mmarko88.github.io (
.windsurf/workflows/cover-image.md). Copyright stays with the author.
Cover image for a post
Usage: /cover-image <post> — <post> is a directory or slug under content/post/ (e.g. cover-image teen_mistakes).
Produces 2–3 candidate cards as SVG + rendered PNG previews; the user picks one. Distilled from OG-image CTR research — do not skip the read-first steps.
Steps
-
Read the post fully (title, description, hook, conclusion). Find the punchline: the most surprising number, the strongest quote, or the core mechanism/takeaway. The card sells the click — do NOT just repeat the H1 on a colored background.
-
Pick a concept type (in priority order — the first that fits the content):
- Proof card — the surprising number / before-vs-after / benchmark shape (best for measured posts; numbers get clicked)
- Quote card — bold typography + attribution badge (interviews, opinions, quotable one-liners)
- Visual metaphor — the article's mechanism compressed into one glance (pipeline, split bar, ✗/✓ list)
- Title card — fallback only: eyebrow tag + shortened title + one-line hook
-
Draft 2–3 SVG variants at
1200x630in the post's page bundle. Each variant must differ in perspective, not just colors/layout — assign each a distinct creative angle, e.g. the reader's-pain angle, the authority/credibility angle, the mechanism angle (persona-based variation is what actually diversifies an idea pool; restyling the same concept does not). For posts about a person, prefer a variant with their real public headshot — faces outperform every other focal point (crop tight, expressive beats neutral). If the user rejects the first set, run a reseed burst: list the rejected concepts as one-line mechanisms and generate only directions not yet proposed.Serving rules (from RESEARCH-cover-image.md — most card failures are here, not design):
shareImagemust be a raster file (PNG/JPG) with a real extension — social crawlers ignore SVG/WebP- Platforms cache cards by URL forever: if re-generating a card for an already-shared post, bump the filename (e.g.
share-v2.png) - JPEG for photos, PNG for text cards; never rely on transparency; keep under a few hundred KB
featureImageAlt/og:image:alt: describe the card in plain words — not a verbatim title repeat
Brand tokens (match existing heroes, e.g.
fp-antipatterns-hero.svg):- Light bg
#f7f9fc/ dark bg#172033; accent barrect12px#1a5fb4at top - Font
Segoe UI, Arial, sans-serifonly; red#ca3f3f(+bg#fde8e8), green#17864b(+bg#d9f2e4), muted#617086(light) /#9aa8bf(dark) - Eyebrow row:
font-size 24,font-weight 700,letter-spacing 2, caps, accent color - Footer:
TOPIC · TOPIC · professionaldev.dev,font-size 18, muted
Layout rules (from research — violations get cropped or ignored):
- Safe zone: keep everything critical inside the center ~1000x500; ≥60px from edges (platforms crop unpredictably)
- Headline 46–72px so it reads at ~300–400px preview width; max 2–3 text elements; 6–10 words of large text max
- One message — billboard, not infographic. If a row needs a label >~35 chars at 22px, shorten it or move the annotation to a separate column (x≥580)
- No fake buttons/CTA chrome; high contrast (dark text on light card or white on
#172033) - Estimate text width ≈
chars × font-size × 0.55; check for overlaps before rendering - Keep text ≤10 words and large — Google Discover recommends against text-heavy og:images (a performance recommendation, not a ban); the card must still read visually without its text
-
Render PNG previews — headless Chrome (works offline, no rsvg/magick needed):
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \ --headless --disable-gpu --window-size=1200,630 \ --screenshot="<abs>/preview-<name>.png" "file://<abs>/hero-<name>.svg"If the SVG ever uses web fonts, wait for
document.fonts.readybefore screenshot —loaddoesn't cover them (Playwright > Puppeteer if this pipeline ever graduates to a script). Alwaysread_fileeach PNG to check it visually — overlaps, clipping, and legibility at ~400px thumbnail width. Fix and re-render before presenting. -
Self-check before presenting (reviewer pass — observable bans, not vibes). For each PNG, verify: nothing critical within 60px of edges; headline ≤10 words and legible at 400px; no fake buttons/CTA chrome; no text overlapping other elements; brand tokens used (accent
#1a5fb4, site font, footer withprofessionaldev.dev); the card reads visually even without its text. Any failure → fix and re-render before the user sees it. -
Present previews to the user. On pick: rename winner to
<slug>-hero.svg(or post's existing convention), re-render it asshare.png, delete losing SVGs/previews. -
Wire front matter — if the post isn't a page bundle yet,
git mv post.md post/index.mdfirst:usePageBundles: true featureImage: '<name>-hero.svg' # hero shown atop the post featureImageAlt: '<what the card literally shows>' shareImage: 'share.png' # PNG — social crawlers ignore SVG/WebP -
Verify on
localhost:1313— post serves 200 and the hero renders. Optionally sanity-check the card with a link-preview debugger (Facebook Debugger, LinkedIn Post Inspector) before the post is shared — crawlers cache the first fetch. Do not commit unless asked.
