Developing templates for the static website generator Hugo? Then these advanced tips & tricks might be helpful to you.
I’ve been working with Hugo for quite a while now. For roughly two years, according to this Git commit. During this time I’ve learned a few things worth sharing.
Rich Link Previews ¶
Open Graph and Twitter Cards enable any web page to become a rich object in a social graph
. This allows previews including title, description, logo, images, author, publisher, etc.
For example, the following preview of the page on twitter.com
linked in the previous paragraph is based on data retrieved from that link:
About Twitter Cards
With Twitter Cards, you can attach rich photos, videos and media experiences to Tweets, helping to drive traffic to your website. Simply add a few lines of markup to your webpage, and users who Tweet links to your content will have a “Card” added to the Tweet that’s visible to their followers.
Shortcode ¶
Here’s how my shortcode works in principle: I use the free API from Microlink to retrieve a json
file with all metadata for a given URL. With Hugo’s data capabilities, I process the file and render the data fields of choice.
There are two ways to retrieve the data: letting Hugo automatically fetch the data directly from Microlink’s API every time it runs—or manually saving Microlink’s json
file once to Hugo’s data
folder and having it Hugo access it locally.
I’ve opted for saving Microlink’s files locally for three reasons:
- The quality of Microlink’s API fluctuates depending on the target URL. Saving the data locally gives me a chance to review and adjust it manually if necessary. It still saves me a ton of time.
- The preview will remain intact even after the target URL is no longer available.
- If you have a large website, builds will take longer when requesting Microlink’s API for every preview. (Which isn’t going to be a big deal for this blog any time soon.)
The downside, of course, is that the data might become outdated over time, essentially displaying an incorrect preview.
Either way, using the shortcode in your content is really … short:
{{<preview-external src="">}}
As src
parameter, you either provide a target URL or the path to the file inside Hugo’s data
directory. Since I save the json
files locally, the corresponding shortcode source looks like this:
{{ with (index .Site.Data (.Get "src")) }}
<div class="shadow card">
<div class="card-body">
<div class="media">
{{ with .data.logo }}
<img src="{{ .url }}" alt="" class="yx-favicon">
{{ end }}
<div class="media-body">
<h6><i class="las la-external-link-alt"></i> <a href="{{ .data.url }}"
class="stretched-link">{{ .data.title | title }}</a></h6>
{{ with .data.description }}<p>{{ . | htmlUnescape | markdownify }}</p>{{ end }}
</div>
</div>
</div>
<div class="card-footer">
<div class="yx-attribution">
{{ with .data.author }}{{ . }}{{ end }}{{ if and .data.author .data.publisher}},
{{ end }}{{ with .data.publisher }}<cite>{{ . }}</cite>{{ end }}</div>
</div>
</div>
{{ end }}
If you want instead to fetch Microlink’s json
response everytime Hugo builds your website, you would change the first line accordingly:
{{ with getJSON (printf "https://api.microlink.io/?url=%s" (.Get "src")) }}
Read on to see how you can easily provide such metadata yourself —and make this even work with responsive images!
Responsive Images in Hugo’s Metadata Shortcodes ¶
There’s a quick and easy way with Hugo to enable your website to be previewed in other apps and websites, too.
Hugo comes with built-in shortcodes for the Open Graph and Twitter Cards protocols. Using the shortcodes is as simple as adding the following lines to your HTML head
element:
{{ template "_internal/opengraph.html" . }}
{{ template "_internal/twitter_cards.html" . }}
These shortcodes take the metadata from your site’s configuration as well as your pages’ front matter and turn it into the corresponding HTML meta
tags. A social media platform like Twitter or a service like Microlink is now capable to retrieve metadata from your webpages.
Hugo’s shortcodes will also consider images and generate the corresponding meta
tags. According to this research, a good practice is to size Open Graph images to 1200×630 pixels.
Hm, yet another size for the cover images of my articles I need to generate and keep track of.
Since I use Cloudinary as a service to resize images on the fly and thus to make my images responsive, the solution is pretty simple.
In the content files’ front matter, I define one image in the .Params.images
array. For this article you’re just reading, it would look like this:
images:
- https://res.cloudinary.com/ypertex/image/upload/c_fill,dpr_auto,f_auto,g_auto,h_630,q_auto,w_1200/7d143c90-862c-4e74-9275-763746bf95f0
Hugo takes this URL and uses it in the two metadata shortcodes opengraph.html
and twitter_cards.html
. I use this URL to show the same cover image in the list of articles—but properly transformed for the size of my users’ devices. To that end, I first have to deconstruct the URL into its parts with the help of Hugo’s path.Split
function:
{{ $cover := (path.Split (index (first 1 .Params.images) 0)).File }}
Now, I can reconstruct different URLs for different transformations of the same image, for example:
<picture>
<source media="(min-width: 1200px)" srcset="{{ .cloudinary.baseURL }}{{ .cloudinary.transformations.index.xl }}{{ $cover }}">
<source media="(min-width: 992px)" srcset="{{ .cloudinary.baseURL }}{{ .cloudinary.transformations.index.lg }}{{ $cover }}">
<source media="(min-width: 768px)" srcset="{{ .cloudinary.baseURL }}{{ .cloudinary.transformations.index.md }}{{ $cover }}">
<source media="(min-width: 576px)" srcset="{{ .cloudinary.baseURL }}{{ .cloudinary.transformations.index.sm }}{{ $cover }}">
<img src="{{ .cloudinary.baseURL }}{{ .cloudinary.transformations.index.xs }}{{ $cover }}">
</picture>
This way, I only need to track one single URL per article for its cover image—and yet can generate responsive images from it.
Conclusion ¶
In this article I shared a few ways how I use Hugo, Microlink, and Cloudinary to my advantage:
- How to generate rich previews of linked content
- How to use Hugo’s metadata shortcodes with responsive images
I hope these ideas can make your life as a content producer and publisher easier, too!
Disclaimer ¶
I am in no way affiliated with the services mentioned in this article. I recommend them as a blogger who employs their free services for personal use.
Michael Schmidle
Founder of PrioMind. Start-up consultant, hobby music producer and blogger. Opinionated about technology, strategy, and leadership. In love with Mexico. This blog reflects my personal views.
Jul 11, 2024 · 3min read
Integrating Termly With Nuxt 3
Integrating Termly’s consent management with Nuxt 3 turns out to be harder than just inserting a script tag. Here’s a solution that resolves hydration mismatches and UI glitches, ensuring smooth functionality and user experience. Continue…
Nov 15, 2023 · 2min read
Mastering Keyboard Interactions in Shadcn-Vue: A Fix for Complex UIs
In the intricate dance of UI components within Vue applications, a misstep can disrupt the rhythm. Discover how a straightforward tweak can harmonize your keyboard interactions in shadcn-vue in complex nested components. Continue…
Sep 26, 2023 · Nov 11, 2023 · 2min read
The Better Nuxt Directus Authentication Middleware
The Nuxt Directus docs give you a basic auth middleware, but it’s got some quirks. Here’s how to bulletproof it. Continue…