diff --git a/content/posts/dynamic-opengraph-images-with-hugo/index.md b/content/posts/dynamic-opengraph-images-with-hugo/index.md index 33a827c..58d2a17 100644 --- a/content/posts/dynamic-opengraph-images-with-hugo/index.md +++ b/content/posts/dynamic-opengraph-images-with-hugo/index.md @@ -21,7 +21,9 @@ During my search, I came across a few different approaches using external servic I ended up borrowing heavily from Aaro's approach with a few variants for the OpenGraph image: - When sharing the home page, the image includes the site description. - When sharing a post, the image includes the post title. -- ... but if the post has a thumbnail listed in the front matter, that gets added to the corner of the `og:image`. +- ... but if the post has a thumbnail[^thumbnail] listed in the front matter, that gets added to the corner of the `og:image`. + +[^thumbnail]: My current theme doesn't make use of the thumbnails, but a previous theme did so I've got a bunch of posts with thumbnails still assigned. And now I've got a use for them again! I'm sure this could be further optimized by someone who knows what they're doing[^future]. In any case, here's what I did to get this working. @@ -76,73 +78,72 @@ To use this new partial, I'll add it to my `layouts/partials/head.html`: which is in turn loaded by `layouts/_defaults/baseof.html`: ```jinja-html - - {{- partial "head.html" . -}} - + + {{- partial "head.html" . -}} + ``` -### Home page OG +### Aaro's OG image generation +[Aaro's code](https://aarol.dev/posts/hugo-og-image/) provides the base functionality for what I need: + +```jinja-html +{{/* Generate opengraph image */}} +{{- if .IsPage -}} + {{ $base := resources.Get "og_base.png" }} + {{ $boldFont := resources.Get "/Inter-SemiBold.ttf"}} + {{ $mediumFont := resources.Get "/Inter-Medium.ttf"}} + {{ $img := $base.Filter (images.Text .Site.Title (dict + "color" "#ffffff" + "size" 52 + "linespacing" 2 + "x" 141 + "y" 117 + "font" $boldFont + ))}} + {{ $img = $img.Filter (images.Text .Page.Title (dict + "color" "#ffffff" + "size" 64 + "linespacing" 2 + "x" 141 + "y" 291 + "font" $mediumFont + ))}} + {{ $img = resources.Copy (path.Join .Page.RelPermalink "og.png") $img }} + + + + + + + + + +{{ end }} +``` + +The [`resources.Get`](https://gohugo.io/functions/resources/get/) bits import the image and font resources to make them available to the [`images.Text`](https://gohugo.io/functions/images/text/) functions, which add the site and page title texts to the image using the designated color, size, placement, and font. + +The `resources.Copy` line moves the generated OG image into the post bundle directory and gives it a clean `og.png` name rather than the very-long randomly-generated name it would have by default. + +And then the `` lines insert the generated image into the page's `` block so it can be rendered when the link is shared on sites which support OpenGraph. + +This is a great starting point for what I want to accomplish, but I'm going to make some changes in my `opengraph.html` partial. + +### My tweaks +As I mentioned earlier, I want to have basically three recipes for baking my OG images: one for the homepage, one for standard posts, and one for posts with an associated thumbnail. They'll all use the same basic code, though, so I wanted to be sure that my setup didn't repeat itself too much. ```jinja-html // torchlight! {"lineNumbers": true} -{{ $base := resources.Get "og_base.png" }} -{{ $font := resources.Get "/FiraMono-Regular.ttf" }} - - - - - - -{{- if .IsHome }} -{{ $img := $base.Filter (images.Text .Site.Params.Description (dict - "color" "#d8d8d8" - "size" 64 - "linespacing" 2 - "x" 40 - "y" 300 - "font" $font -))}} -{{ $img = resources.Copy "og.png" $img }} -{{ .Scratch.Set "og_image" $img }} -{{- end }} - -{{- if .IsPage }} -{{- $iso8601 := "2006-01-02T15:04:05-07:00" -}} - -{{ with .PublishDate }}{{ end }} -{{ with .Lastmod }}{{ end }} -{{- end -}} - -{{- with .Params.audio }}{{ end }} -{{- with .Params.locale }}{{ end }} -{{- with .Site.Params.title }}{{ end }} -{{- with .Params.videos }}{{- range . }} - -{{ end }}{{ end }} -``` - -### Post OG - -```jinja-html -{{ $base := resources.Get "og_base.png" }} +{{ $img := resources.Get "og_base.png" }} {{ $font := resources.Get "/FiraMono-Regular.ttf" }} +{{ $text := "" }} - {{- if .IsHome }} -{{ $img := $base.Filter (images.Text .Site.Params.Description (dict - "color" "#d8d8d8" - "size" 64 - "linespacing" 2 - "x" 40 - "y" 300 - "font" $font -))}} -{{ $img = resources.Copy "og.png" $img }} -{{ .Scratch.Set "og_image" $img }} +{{ $text = .Site.Params.Description }} {{- end }} {{- if .IsPage }} @@ -150,11 +151,15 @@ which is in turn loaded by `layouts/_defaults/baseof.html`: {{ with .PublishDate }}{{ end }} {{ with .Lastmod }}{{ end }} -{{ with .Params.thumbnail }} +{{ $text = .Page.Title }} +{{ end }} + +{{- with .Params.thumbnail }} {{ $thumbnail := $.Resources.Get . }} {{ with $thumbnail }} -{{ $img := $base.Filter (images.Overlay (.Process "fit 300x250") 875 38 )}} -{{ $img = $img.Filter (images.Text $.Page.Title (dict +{{ $img = $img.Filter (images.Overlay (.Process "fit 300x250") 875 38 )}} +{{ end }}{{ end }} +{{ $img = $img.Filter (images.Text $text (dict "color" "#d8d8d8" "size" 64 "linespacing" 2 @@ -163,22 +168,6 @@ which is in turn loaded by `layouts/_defaults/baseof.html`: "font" $font ))}} {{ $img = resources.Copy (path.Join $.Page.RelPermalink "og.png") $img }} -{{ $.Scratch.Set "og_image" $img }} -{{ end }} -{{ else }} -{{ $img := $base.Filter (images.Text .Page.Title (dict - "color" "#d8d8d8" - "size" 64 - "linespacing" 2 - "x" 40 - "y" 300 - "font" $font -))}} -{{ $img = resources.Copy (path.Join $.Page.RelPermalink "og.png") $img }} -{{ .Scratch.Set "og_image" $img }} -{{ end }} -{{- end -}} -{{ $img := .Scratch.Get "og_image" }} @@ -193,5 +182,4 @@ which is in turn loaded by `layouts/_defaults/baseof.html`: {{- with .Params.videos }}{{- range . }} {{ end }}{{ end }} - ``` \ No newline at end of file