mykiwi/mykiwi.blogpublic Fork
⑂ c2b139d
Commits
⬇ Clone ▾
git clone https://git.rickub.com/mykiwi/mykiwi.blog.git
git clone ssh://git@rickub.com/mykiwi/mykiwi.blog.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

Put a page's representative image behind one partial

og:image and JSON-LD's image want the same picture, chosen the same way,
and computing that twice is how the two end up disagreeing. page-image.html
takes a page and returns a dict of url/width/height; nothing uses it yet.

The priority is the one opengraph.html already had - front matter `images`,
then the generated og-card.png, then the site avatar - with one correction
carried in: the og-card step now requires the page to be in the posts
section rather than merely being a .IsPage. flake.nix finds what to
screenshot by globbing $out for /YYYY/MM/DD/slug/ directories, so a
standalone page is a .IsPage that no og-card.png is ever written for, and
would otherwise advertise a 404 as its card image. It falls through to the
avatar instead.

width/height are 0 when unknown, which is only the front-matter case: an
arbitrary reader-supplied path is not a Hugo resource this can measure.
Romain Gautier committed 2026-09-23T22:58:20+02:00 Browse files
c2b139d parent: cdc5ae7
added blog/layouts/partials/page-image.html +47 -0
new file mode 100644
@@ -0,0 +1,47 @@
1+{{- /*
2+ The image that represents a page - shared between opengraph.html (og:image/
3+ twitter:image) and jsonld.html (BlogPosting.image), so the same priority
4+ logic can't drift between the two the way it would copied twice. Takes the
5+ page being rendered, returns a dict of url/width/height (width/height 0
6+ when unknown, which is only the front-matter-`images` case: an arbitrary
7+ reader-supplied path isn't a Hugo resource this can measure).
8+
9+ Priority: front matter `images` (Hugo's own convention) wins, in case a
10+ post ever wants to hand-pick its own; then the generated card every post
11+ gets (og-card.png, a real Chromium screenshot of this same page taken by
12+ flake.nix's buildPhase - not present under plain `hugo`/`hugo server`,
13+ only the Nix build, so a local preview falls through to the avatar
14+ instead); the site avatar is the last resort so a page never has no image
15+ at all.
16+
17+ The og-card step is for posts specifically, not for pages in general:
18+ flake.nix finds what to screenshot by globbing $out for /YYYY/MM/DD/slug/
19+ directories, which is the posts permalink pattern from hugo.toml and
20+ nothing else. A standalone page - /talks/ - is a .IsPage all the same, so
21+ testing that alone had it advertise an og-card.png that no build step ever
22+ writes. It falls through to the avatar instead, which is a real image.
23+*/ -}}
24+{{- $page := . }}
25+{{- $url := "" }}
26+{{- $width := 0 }}
27+{{- $height := 0 }}
28+
29+{{- with $page.Params.images }}
30+ {{- with index . 0 }}{{ $url = . | absURL }}{{ end }}
31+{{- end }}
32+{{- if and (not $url) $page.IsPage (eq $page.Section "posts") }}
33+ {{- $url = printf "%sog-card.png" $page.Permalink }}
34+ {{- $width = 1200 }}
35+ {{- $height = 630 }}
36+{{- end }}
37+{{- if not $url }}
38+ {{- with site.Params.profile.avatar }}
39+ {{- with resources.Get . }}
40+ {{- $url = .Permalink }}
41+ {{- $width = .Width }}
42+ {{- $height = .Height }}
43+ {{- end }}
44+ {{- end }}
45+{{- end }}
46+
47+{{- return (dict "url" $url "width" $width "height" $height) }}
new file mode 100644
@@ -0,0 +1,47 @@
1+{{- /*
2+ The image that represents a page - shared between opengraph.html (og:image/
3+ twitter:image) and jsonld.html (BlogPosting.image), so the same priority
4+ logic can't drift between the two the way it would copied twice. Takes the
5+ page being rendered, returns a dict of url/width/height (width/height 0
6+ when unknown, which is only the front-matter-`images` case: an arbitrary
7+ reader-supplied path isn't a Hugo resource this can measure).
8+
9+ Priority: front matter `images` (Hugo's own convention) wins, in case a
10+ post ever wants to hand-pick its own; then the generated card every post
11+ gets (og-card.png, a real Chromium screenshot of this same page taken by
12+ flake.nix's buildPhase - not present under plain `hugo`/`hugo server`,
13+ only the Nix build, so a local preview falls through to the avatar
14+ instead); the site avatar is the last resort so a page never has no image
15+ at all.
16+
17+ The og-card step is for posts specifically, not for pages in general:
18+ flake.nix finds what to screenshot by globbing $out for /YYYY/MM/DD/slug/
19+ directories, which is the posts permalink pattern from hugo.toml and
20+ nothing else. A standalone page - /talks/ - is a .IsPage all the same, so
21+ testing that alone had it advertise an og-card.png that no build step ever
22+ writes. It falls through to the avatar instead, which is a real image.
23+*/ -}}
24+{{- $page := . }}
25+{{- $url := "" }}
26+{{- $width := 0 }}
27+{{- $height := 0 }}
28+
29+{{- with $page.Params.images }}
30+ {{- with index . 0 }}{{ $url = . | absURL }}{{ end }}
31+{{- end }}
32+{{- if and (not $url) $page.IsPage (eq $page.Section "posts") }}
33+ {{- $url = printf "%sog-card.png" $page.Permalink }}
34+ {{- $width = 1200 }}
35+ {{- $height = 630 }}
36+{{- end }}
37+{{- if not $url }}
38+ {{- with site.Params.profile.avatar }}
39+ {{- with resources.Get . }}
40+ {{- $url = .Permalink }}
41+ {{- $width = .Width }}
42+ {{- $height = .Height }}
43+ {{- end }}
44+ {{- end }}
45+{{- end }}
46+
47+{{- return (dict "url" $url "width" $width "height" $height) }}