feat(website): share card for /logo/ (og:image) so links to the vote get a preview
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MScAinbyMdeNc7H2BZdnnG
This commit is contained in:
parent
58a99a0d9e
commit
c3c59b4bea
5 changed files with 36 additions and 0 deletions
|
|
@ -5,6 +5,7 @@ translationKey: "logo"
|
||||||
layout: single
|
layout: single
|
||||||
type: poll
|
type: poll
|
||||||
poll: logo
|
poll: logo
|
||||||
|
image: /img/logo/vote-card.png
|
||||||
sitemap:
|
sitemap:
|
||||||
priority: 0.5
|
priority: 0.5
|
||||||
m:
|
m:
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ url: /logo/
|
||||||
layout: single
|
layout: single
|
||||||
type: poll
|
type: poll
|
||||||
poll: logo
|
poll: logo
|
||||||
|
image: /img/logo/vote-card.png
|
||||||
sitemap:
|
sitemap:
|
||||||
priority: 0.5
|
priority: 0.5
|
||||||
m:
|
m:
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,10 @@
|
||||||
<meta property="og:description" content="{{ with .Params.description }}{{ . }}{{ else }}{{ site.Params.description }}{{ end }}">
|
<meta property="og:description" content="{{ with .Params.description }}{{ . }}{{ else }}{{ site.Params.description }}{{ end }}">
|
||||||
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}">
|
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}">
|
||||||
<meta property="og:url" content="{{ .Permalink }}">
|
<meta property="og:url" content="{{ .Permalink }}">
|
||||||
|
{{ with .Params.image }}<meta property="og:image" content="{{ . | absURL }}">
|
||||||
|
<meta property="og:image:width" content="1200">
|
||||||
|
<meta property="og:image:height" content="630">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">{{ end }}
|
||||||
{{ $parts := split .Site.Language.LanguageCode "-" }}<meta property="og:locale" content="{{ index $parts 0 }}{{ if gt (len $parts) 1 }}_{{ upper (index $parts 1) }}{{ end }}">
|
{{ $parts := split .Site.Language.LanguageCode "-" }}<meta property="og:locale" content="{{ index $parts 0 }}{{ if gt (len $parts) 1 }}_{{ upper (index $parts 1) }}{{ end }}">
|
||||||
{{ range .AllTranslations }}
|
{{ range .AllTranslations }}
|
||||||
<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .Permalink }}">
|
<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .Permalink }}">
|
||||||
|
|
|
||||||
BIN
website/static/img/logo/vote-card.png
Normal file
BIN
website/static/img/logo/vote-card.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -232,7 +232,37 @@ def b64png(im):
|
||||||
return "data:image/png;base64," + base64.b64encode(buf.getvalue()).decode()
|
return "data:image/png;base64," + base64.b64encode(buf.getvalue()).decode()
|
||||||
|
|
||||||
|
|
||||||
|
def vote_card(path):
|
||||||
|
"""1200x630 share card for /logo/: M on cream, R on ink, side by side."""
|
||||||
|
W, H = 1200, 630
|
||||||
|
im = Image.new("RGBA", (W, H), "#f7f6f3")
|
||||||
|
ImageDraw.Draw(im).rectangle([W // 2, 0, W, H], fill=MARKS["r"]["ink"])
|
||||||
|
for k, cx in (("m", W // 4), ("r", 3 * W // 4)):
|
||||||
|
m = mark_png(k, "flat", 330)
|
||||||
|
im.alpha_composite(m, (cx - m.width // 2, 110 - (m.height - 330) // 2))
|
||||||
|
size = 46
|
||||||
|
d = ImageDraw.Draw(im)
|
||||||
|
for text, cx, col in (("M", W // 4, "#6b6b6f"), ("R", 3 * W // 4, "#8a8a90")):
|
||||||
|
paths, tw = wordmark(text, size)
|
||||||
|
# letters via the same outlines: rasterise a tiny SVG for crisp text
|
||||||
|
svgtxt = (f'<svg {XMLNS} viewBox="0 -{size} {tw:.0f} {size * 1.3:.0f}">'
|
||||||
|
f'<g fill="{col}">{paths}</g></svg>')
|
||||||
|
t = raster(svgtxt, round(tw), round(size * 1.3))
|
||||||
|
im.alpha_composite(t, (cx - t.width // 2, 500))
|
||||||
|
# url line, centred on the seam
|
||||||
|
paths, tw = wordmark("furtka.org/logo", 40)
|
||||||
|
svgtxt = (f'<svg {XMLNS} viewBox="0 -40 {tw:.0f} 52"><g fill="#c03a28">{paths}</g></svg>')
|
||||||
|
t = raster(svgtxt, round(tw), 52)
|
||||||
|
pad = 18
|
||||||
|
box = Image.new("RGBA", (t.width + 2 * pad, t.height + 2 * pad), "#f7f6f3")
|
||||||
|
ImageDraw.Draw(box).rounded_rectangle([0, 0, box.width - 1, box.height - 1], 14, outline="#e4e3dc")
|
||||||
|
box.alpha_composite(t, (pad, pad))
|
||||||
|
im.alpha_composite(box, (W // 2 - box.width // 2, 40))
|
||||||
|
im.convert("RGB").save(path, optimize=True)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
vote_card(os.path.join(SITE, "static", "img", "logo", "vote-card.png"))
|
||||||
for k in MARKS:
|
for k in MARKS:
|
||||||
out = os.path.join(SITE, "static", "img", "logo", k)
|
out = os.path.join(SITE, "static", "img", "logo", k)
|
||||||
os.makedirs(out, exist_ok=True)
|
os.makedirs(out, exist_ok=True)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue