Add Open Graph link previews to photo pages

Shared links now unfurl with an image in WhatsApp, Telegram and anything
else that reads Open Graph, instead of showing the bare URL.

A dedicated og/ rendition is generated per photo: 1200px longest side,
quality laddered down until it fits under ~250 KB. WhatsApp drops the
preview entirely once the image passes ~300 KB, and the medium rendition
can exceed that, so it is not reused. Dimensions for og:image:width and
og:image:height are read back from the encoded file with DecodeConfig, so
they are emitted even when the rendition itself was skipped as up to date.

The og:image and og:url values are absolute via BaseURL; both crawlers
ignore relative image paths. Previews therefore only work against the
deployed base URL, not http://localhost.
This commit is contained in:
2026-08-24 13:59:49 +02:00
parent eb6dba6eb0
commit d4fec5b0ff
3 changed files with 129 additions and 8 deletions
+19
View File
@@ -4,6 +4,25 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{.Photo.Caption}}</title>
<!-- Open Graph + Twitter card: the preview shown when the link is shared to
WhatsApp, Telegram, etc. URLs are absolute because both crawlers ignore
relative image paths. Served from public/og/, kept under ~250 KB. -->
<meta property="og:type" content="article">
<meta property="og:site_name" content="{{.Author}}">
<meta property="og:title" content="{{.Photo.Caption}}">
<meta property="og:description" content="{{.Author}} — {{.Photo.Date.Format "January 2, 2006"}}">
<meta property="og:url" content="{{.BaseURL}}/photo/{{.Photo.Slug}}/">
<meta property="og:image" content="{{.BaseURL}}/{{.Photo.OG}}">
<meta property="og:image:type" content="image/jpeg">
{{if .Photo.OGWidth}}<meta property="og:image:width" content="{{.Photo.OGWidth}}">
<meta property="og:image:height" content="{{.Photo.OGHeight}}">{{end}}
<meta property="og:image:alt" content="{{.Photo.Caption}}">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{.Photo.Caption}}">
<meta name="twitter:description" content="{{.Author}} — {{.Photo.Date.Format "January 2, 2006"}}">
<meta name="twitter:image" content="{{.BaseURL}}/{{.Photo.OG}}">
<link rel="stylesheet" href="{{.FontsURL}}">
<link rel="stylesheet" href="/static/style.css">
<style>:root { --serif: '{{.SerifFamily}}', Georgia, serif; --mj: '{{.MlFamily}}', sans-serif; }</style>