Share cards that render themselves — LearnStart's OG set, built from the site's own components
LearnStart had no og:image at all: every link anyone shared unfurled as a bare grey box. It now ships four share cards across banner, WhatsApp-tall, portrait, and square — and none of them are drawn by an image library. The card is a real Astro page built from the real FlameMark and the real theme tokens, photographed by headless Chrome. Change a gradient token and the share card changes with it.
Why Care?
Before today, sharing a LearnStart link anywhere — iMessage, WhatsApp, Slack, LinkedIn — produced a grey rectangle. For a firm whose whole pitch is we are the recognized Pre-Seed arm of Learn Capital, the unfurl was doing the opposite of that work.
There are now four cards, and they carry the positioning in three beats — wordmark, promise, proof:
LearnStart · Pre-Seed & Seed From mindset to grindset. Transforming the way the world learns.
The Interesting Part — the card is a page, not a picture
The obvious way to build share imagery is to draw it: a canvas library, a font file, a pile of x/y coordinates. We started there and threw it away.
Instead the card lives at src/pages/og/[format].astro, and it is composed of
the site's own parts — the real FlameMark component (same geometry as the
favicon, seed 15), the real --gradient-accent token, the real Inter and
JetBrains Mono webfonts. scripts/shoot-og-cards.ts only photographs those
pages, with headless Chrome at each card's exact pixel size so nothing is ever
scaled between markup and delivered JPEG.
The payoff is that the share card can't drift from the brand. Re-point
--grad-from in theme.css and the flame on the card moves with it, because
it's the same custom property the site reads. There is no second copy of the
brand to forget to update.
Two Layers, and the Split Is the Discipline
Ideogram generates the field — wordless flame ribbons rising from a low
horizon, on the navy-and-forest palette read straight out of DESIGN.md. It
never draws a letter; the negative prompt spends tokens forbidding it. Every
locked channel (palette, seed, negative prompt, rendering speed) lives in
DESIGN.md's imagery: block, so only the prompt and the aspect ratio vary per
run and a generation six months from now lands in the same visual family.
Everything legible — flame, wordmark, eyebrow, headline, sub — is markup composited on top.
The chosen field went through two rounds of curation before it landed: a radiant burst rising off the right edge, rays fanning left across the frame, which is what the veil is tuned around.
Four Formats, Because Chat Clients Crop
WhatsApp and iMessage are the primary targets, so BannerTall (1080×1440) is a
first-class deliverable, not an afterthought. Wide cards put copy beside the
subject behind a left-to-right veil; tall cards put it above, because chat
clients aggressively top-crop tall previews.
Two source fields exist rather than one: cropping the 16:9 field into a 3:4 frame threw the flames away entirely. Generate at the ratio you'll actually use.
The tall field is deliberately a different composition from the banner's — a dark sky over flame ribbons along the bottom, rather than the banner's burst off the right edge. That's not an oversight. A tall run aimed at matching the burst produced four unusable candidates, every one with a bright sky where the cream headline has to sit. Same palette, same flame motif, different composition, and legible — which beats matching and unreadable.
Two Prompt Lessons, Learned Expensively
Both are now encoded in DESIGN.md so the next run doesn't rediscover them:
A "left half … right half …" prompt renders a literal diptych — a hard vertical seam splitting the canvas into two unrelated panels, in all four candidates. The fix is to say "one single continuous unbroken field" and keep
split screen, diptych, vertical dividerin the negative prompt.Empty space is never left as residue. It has to be declared first, as its own renderable thing with concrete content ("the top 1/2 is empty negative space"), or the subject grows to fill the canvas and swallows the zone the overlay needs.
Also Included
BaseLayout now emits the full unfurl surface — canonical URL, og:url,
og:site_name, twitter:card, and the image dimensions. og:image is absolute
(built from site in astro.config.mjs), because scrapers fetch it out of
context and reject relative paths. The cards are JPEG rather than WebP: iMessage
and WhatsApp are the least forgiving previewers, and og:image:type has to match
the actual bytes or the unfurl silently fails.
