Context
Link-preview crawlers (Slack, Twitter, iMessage, agent integrations) currently render no preview when a paweldregan.com URL is shared — the pages have no Open Graph or Twitter Card meta tags. An agent recently flagged it because it couldn't find the site reliably from a shared link.
A first attempt landed in commit 07b21ef — full per-page <meta property="og:*"> + <meta name="twitter:*"> blocks added directly inside each page's <head>. That implementation was reverted in the working tree because it duplicated meta blocks across all 5 pages and bypassed the site-level config.
The image assets transferred from stacksjs/ultrarunner-paw (public/images/*.jpg, including og.jpg) are still committed and useful here either way.
Goal
Hook OG / Twitter meta into the existing site.config.ts per-page metadata so each page automatically renders the right tags without duplicating boilerplate per .stx file.
The shape is already there:
// site.config.ts
pages: {
'/': {
title: '…',
description: '…',
priority: 1.0,
changefreq: 'weekly',
},
'/about': { … },
'/races': { … },
'/coaching': { … },
}Each page declaration just needs to extend with (or default to) an image field, and the layout/head needs to render the resolved values into the right <meta> tags.
Scope
- Extend
site.config.tspages: {}entries with an optionalimagefield (defaults to a site-wideseo.defaultImage). - Add an
seo.defaultImagetodefineSiteConfig'sseosection pointing at/images/og.jpg. - Implement a single shared
<head>partial / mechanism that, given the current route, looks up the page config and emits:<meta name="description">(uses page'sdescription)- Open Graph:
og:type,og:site_name,og:title,og:description,og:url,og:image,og:image:width,og:image:height,og:locale - Twitter:
twitter:card=summary_large_image,twitter:site=@ultrarunnerpaw,twitter:title,twitter:description,twitter:image
- Locale-aware: when the active locale is
deorpl, the metadescriptionshould pull from the matching translation. Same forog:locale(en_US/de_DE/pl_PL). - 404 page: keep
<meta name="robots" content="noindex">but still render a sensible OG block (so a shared 404 link still previews the brand).
Verification
- View-source on each page (
/,/about,/races,/coaching, plus a 404) and confirm the meta tags are present + correct. - Paste each URL into the Twitter Card validator and the Facebook Sharing Debugger — preview should show the right title, description, and image.
- Paste in Slack/iMessage — same.
Out of scope
Dynamic per-page OG image rendering (Swiss Alps bg + per-page text overlay) is its own issue.