Creating a new shortcode with Hugo
For those of you not familiar with Hugo, it’s the tool with which I’m generating this blog. Hugo is a static website engine similar to Jekyll or Hexo if you’re familiar with those. You write your content in markdown format, and it generates a set of static files, from which your blog is served. It’s written in Go and it’s very fast.
Just in case if you get featured on Reddit, Slashdot or Hackernews, this might be the difference between your server failing under high traffic, or smoothly delivering all the content to a larger than usual viewership. Static files mean a minimal CPU impact to your web server, so you can rest assured that it would take a very extraordinary event to kill your server, even if it’s not very new or fast.
There were many improvements that I did to Hugo, but most of them have just been made to handle certain social features that improve how this blog is shared, or to improve the look and feel of the blog. In fact, there’s an “About the author” section lower down on the page, where I collect peoples e-mails so I can notify them about new posts. This might be the only dynamic content on the page, your email is sent to an API via HTTPS and stored in a database. And a few times per month, I write an e-mail to you guys by hand and let you know of any new posts.
Hugo supports writing content plugins, or “shortcodes”, which enable you to embed external content or provide functionality in addition to the text content which you write. For example, I wrote a shortcode that makes it easy for people to tweet quotes from your article. You can see it in use like this:
"Adding a "Tweet this" shortcode to Hugo, step-by-step tutorial" via @TitPetric
Click to Tweet
The short code for this looks a little bit (exactly) like this:
There’s only a few steps to creating a shortcode like this.
Create the HTML snippet
In order to create a snippet, I needed to create a new template file for it.
This template file needs to be created in the theme, saved into layouts/shortcodes/tweet.html
.
In case this folder doesn’t exists, you can create it.
As you can see, this HTML file is basically a standard Go html/template file. There are only a few notable things about this shortcode:
- I added a class
.tweet-this
so I can style the contents appropriately, - The variable
.Page.Permalink
containes the link to the post which we want to share to twitter, - Using
{{ .Get 0 }}
retrieves the first argument to the shortcode,
Depending on your theme, you might need to provide a Twitter icon. I am using FontAwesome.
Using .tweet-this
as the selector, we can style the widget we’re creating appropriately.
Styling the widget
Styling the widget is a bit more complex. Due to the theme this blog is using as a base, many CSS properties
have a higher specificity than just referencing the .tweet-this
class. We can solve this using only two
possible approaches:
- We can increase CSS specificity by using more explicit selectors or IDs,
- We can use the
!ignore
keyword for our CSS properties to make them “sticky”.
Generally the second one is pretty bad practice, but unfortunately, the issue here is with the theme itself, which also doesn’t exactly follow best practices for writing CSS. Just in case you need a reminder how CSS specificity works, look at an older article of mine, CSS resets are broken. It’s just as true today as it was then.
.tweet-this {
background: #fff;
border: 1px solid #ccc;
padding: 0.6em 1em;
font-size: 1.3em;
}
.tweet-this > p {
letter-spacing: 1px;
line-height: 1.42 !important;
}
.tweet-this > p > a {
text-decoration: none !important;
color: #555 !important;
}
.tweet-this > p > a:hover {
color: #333 !important;
}
.tweet-this > a {
color: #55acee !important;
text-decoration: none !important;
display: block;
text-align: right;
font-size: 0.8em;
}
.tweet-this > a > i {
margin-right: 0.3em;
vertical-align: middle;
}
I am using a method called “nesting” to prevent the pollution to the global namespace. Unfortunately, I had
to use a number of !important
rules here to override defaults that apply to the article, but are unfortunately
more specific. As I didn’t want to resort to IDs (#tweet-this) or similar, this does become somewhat of a best
effort approach to style the widget within the current theme.
Conclusion
If you want to write a widget for Hugo, it’s very easy to do so. You might struggle with the finer points of Go template system if you want to take advantage of it, but if your widget can be represented in pure HTML and Javascript, then adding pretty much anything to your blog contents is possible. And here’s one more example of seeing our widget in action:
"Writing a Hugo Widget that lets readers share your content on Twitter" via @TitPetric
Click to Tweet
While I have you here...
It would be great if you buy one of my books:
- Go with Databases
- Advent of Go Microservices
- API Foundations in Go
- 12 Factor Apps with Docker and Go
Feel free to send me an email if you want to book my time for consultancy/freelance services. I'm great at APIs, Go, Docker, VueJS and scaling services, among many other things.
Want to stay up to date with new posts?
Stay up to date with new posts about Docker, Go, JavaScript and my thoughts on Technology. I post about twice per month, and notify you when I post. You can also follow me on my Twitter if you prefer.