Skip to content
Development

Giving every share link a face

By Victor Da Luz
astroseodev-logsite

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

You might also find useful

Airalo

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 more
NordPass

NordPass

Password manager from the team behind NordVPN, with a free tier.

As a NordPass affiliate, I earn from qualifying purchases.

Learn more
Proton

Proton 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