Giving every share link a face
I pasted a link to imperfectsystems.com into a chat the other day and it came back naked: title, a line of description, no image. Every share of the site looked like that. I’d wired up Open Graph tags months ago and assumed they were doing their job. They weren’t.
The Layout only emitted og:image when something passed it an image prop. Nothing ever did. No page set one, no blog post had a hero image, so the guard quietly evaluated to nothing on every render:
const ogImage = image ? new URL(image, Astro.site).toString() : undefined;
// ...
{ogImage && <meta property="og:image" content={ogImage} />}
The fix is one line. Default the prop, and the guard becomes dead code:
image = '/assets/og-default.png',
// ...
const ogImage = new URL(image, Astro.site).toString();
Blog posts still win when they set a hero image, because image={entry.data.heroImage} passes undefined when there’s no hero, and an undefined value is exactly what triggers the destructuring default. No special-casing needed. I also added the twitter:card set and og:image:width/height/alt while I was in there.
The more interesting part was making the image. The issue said, in so many words, don’t just reuse the logo. So I built a proper 1200x630 card: a little terminal window, a green $ ./run --software --games --music with a neon glow, the brand mark, the URL. I wrote it as a plain HTML file and screenshotted it with headless Chrome, then squeezed it through pngquant. Flat neon-on-black quantizes beautifully: 20KB out the door.
One gotcha cost me a minute of confusion. My first render came out 2400x1260. On a Retina Mac, headless Chrome inherits the 2x scale factor and silently doubles your window size. The fix:
--force-device-scale-factor=1
The last lesson is one I keep relearning: build success is not deploy success. Locally I confirmed the tags were in the built HTML with absolute URLs, which felt like proof. But the homepage is server-rendered, so there’s no static file to inspect. The only real check is the live one. After the deploy I curled the actual page:
curl -s https://imperfectsystems.com/ | grep og:image
# <meta property="og:image" content="https://imperfectsystems.com/assets/og-default.png"
There it is. Now the links have a face.
Related reading
The 404 that was already correct, and the robots.txt that wasn't
A Sitemap directive that had to point at the index, a 404 fix that almost got overbuilt, and a documented Cloudflare behavior that didn't materialize when checked.
Rebasing an affiliate PR into a build dependabot quietly broke
A grouped 12-update dependabot bump hid a Tailwind major that broke loudly and an Astro major that broke silently, triggered by one unmerged branch.
The landing page copy that competed in the wrong category
The marketing page pitched new-release tracking - an incumbent's home turf - while the view model's doc comment had the real pitch all along.
You might also find useful
Airalo eSIM
Local data eSIM for travel - no physical SIM swap needed.
This is my Airalo referral link. You get a discount on your first eSIM, and I earn Airalo credit toward mine.
Learn moreNordPass
Password manager from the team behind NordVPN, with a free tier.
As a NordPass affiliate, I earn from qualifying purchases.
Learn moreProton Drive
Encrypted cloud storage from the team behind Proton Mail.
As a Proton Partner, I earn from qualifying purchases of Proton's privacy and security services (Pass, Mail, VPN, Drive).
Learn more