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

Development

The description nobody wrote

Bing said the site's meta descriptions were too short. Almost every page had a good one - except the homepage and the blog index, the two pages everybody actually lands on.

Read