Really crude attempt at recreating in Hugo the link preview feature that you see on various social networks.
My result:
Hugo is the world's fastest static website engine. It's written in Go (aka Golang) and developed by bep, spf13 and friends.
To do this I used the iframely.com API together with some precautions to avoid hitting the request limit.
How the API works
Iframely offer 2 API endpoints: “oEmbed” and “Iframely”. The first is good enough for a basic link preview and follows some standard formatting so we are secure regarding API changes. The latter is more feature rich but it’s overblown for my use case, I think it would be trivial enough to implent on your own if you want.
How to use it in your theme
We are just going to implement a simple Hugo Shortcode to display an automatic link preview
To use in your markdown file:
{{<oembed "https://gohugo.io/">}}
The API key to put in your config.toml
[params]
iframely = "1234567890pleasechangeme"
In your layouts/partials/oembed.html
{{ $url := (index .Params 0) }}
{{ $reqUrl := printf "https://iframe.ly/api/oembed?url=%s&api_key=%s" $url $.Site.Params.iframely }}
{{ with $oembed := getJSON $reqUrl }}
{{ with .Err }}
{{ warnf "%s" . }}
<div>
<a href="{{ $url }}">{{ $url }}</a>
</div>
{{ else }}
<div>
{{with .thumbnail_url }}
{{ with resources.GetRemote . }}
<img
src="{{ (.Fill "200x200 smart webp q90" ).RelPermalink }}"
/>
{{end}}
{{end}}
<div >
<a href="{{.url}}">🔗 {{.title}}</a>
{{ with .description }}<p>{{.}}</p>{{end}}
</div>
</div>
{{ end }}
{{ end }}
You can obviusly change the layout of the shortcode and style it with CSS as you please, this is just a proof of concept.
Notice how
How to not hit the API limit.
Hugo can cache the JSON requests and use them to avoid depleting your API quota at every render. In your config.toml
:
[caches]
[caches.getjson]
maxAge = -1
Be sure to save the cache between renders if your “deploy infrastructure” resets at every run. If you run it on Netlify it should save everything out of the box, if you are like me and use Github Actions then there is some fiddling to do.
For my setup the easiest way was to change the JSON cache folder and then push the eventual new JSON cache back to my repository.
Back in your config.toml
:
[caches]
[caches.getjson]
dir = ':resourceDir/_gen/'
maxAge = -1
And then in your Github Actions workflow.yml
, after the rendering:
- name: GIT Commit Build Artifacts (coverage, dist, devdist, docs)
# Only run on main branch push (e.g. after pull request merge).
if: github.event_name == 'push'
run: |-
git add .
git diff
git config --global user.email "yourprivatemail@users.noreply.github.com"
git config --global user.name "GitHub Action Bot"
git commit -m "auto-update resource cache" -a || echo "No changes to commit"
git push
shell: bash
To avoid a recursive loop where pushing back to your repo triggers a second render we need to ignore the commits to the cache directory:
on:
push:
branches:
- main
paths-ignore:
- 'resources/_gen/**'
This simple trick can help you stay in your monthly quota without any worries. You can easily spot the before and after in this graph.