Adding Bluesky links, buttons and icons to my Hugo site
- hugo
- 2024-11-17
- 9 minutes to read
- bluesky
- gethugomodules
Table of Contents
Introduction
The migration from Twitter to Bluesky is picking up speed, so I thought I would explore adding Bluesky links to my Hugo site. I now have a Bluesky social link and share to Bluesky button! I had to jump through a few hoops to get it working, so here’s how I did it. Because themes are so varied, it is likely that you will have to adjust your approach for your theme, but at the very this post should help give you a rough path.
How to share to Bluesky
A link to my profile is easy, so I started with what does the share to Bluesky url need to look like. A very helpful document in the Bluesky docs on Action Intent Links explains this clearly and this URL example is given. It looks like this:
https://bsky.app/intent/compose?text=I%27m%20reading%20through%20the%20Bluesky%20API%20docs%21%20%F0%9F%A6%8B%0Ahttps%3A//docs.bsky.app
I need to provide a text string for the message. It has to use url escaping and it needs to have a limit of 300 characters. So a quick parameterising of this URL looks like this:
https://bsky.app/intent/compose?text={{ $text | urlquery }}
I try to keep my post titles between 60 and 70 characters therefore, my post url will be somewhere in the region of 100 characters max. The additional text I will add to the message will be less than 100 characters so I’m not going to worry about setting some sort of test on the length of the text. I will then generate a text string that I will pass into my $text
variable and that will become the Bluesky post text. The use of the urlquery
function will escape the string for me.
Social link to Bluesky
I am going to add my bluesky handle as a parameter in my config file. I’m not likely to change my handle, but it’s good practice as it means if I ever update my handle I only need to update it in one place. I will place it in my params.toml
file at the root level:
bluesky = '@justinjbird.me'
I can then address that parameter using {{ .Site.Params.bluesky }}
in my templates.
Fontawesome icon
On the Action Intent Links page it says that there is a fontawesome icon available! It is listed as fa-brands fa-bluesky
.
Some things to note down from the Bluesky fontawesome page:
- The icon is in the brands iconset.
- The unicode for the icon is
e671
. - The class for the icon is
fa-brands fa-bluesky
. - You may need to copy the svg code for the icon for use later.
I had to check that my site was configured to load the brands iconset. This was present in my config.toml
file:
[[params.plugins.css]]
link = "plugins/font-awesome/v6/brands.css"
lazy = true
Adding the share to Bluesky icon to my page
My theme has one page for blog pages found at layouts/blog/single.html
, it calls a partial called social-share
. The block of code looks like this:
{{- partial "social-share" (dict "Context" . "Class" "share-icons" "Title" "" "Whatsapp" false "Telegram" false "Linkedin" true "Pinterest" false "Tumblr" false "Vk" false "Facebook" false) -}}
It constructs a dictionary of parameters that are passed to the social-share
partial. I added the Bluesky
parameter and set it to true
:
{{- partial "social-share" (dict "Context" . "Class" "share-icons" "Title" "" "Bluesky" true "Whatsapp" false "Telegram" false "Linkedin" true "Pinterest" false "Tumblr" false "Vk" false "Facebook" false) -}}
This will pass the Bluesky
parameter to the social-share
partial. However, the icon didn’t appear, so next I had to work out what changes were needed for the social-share partial.
Overriding the social-share module
I’m using the Hugoplate theme. It uses the social-share module by gethugothemes. I know this because there is a go.mod
file in the root of my repository that references it:
module hugoplate.netlify.app
go 1.20
require (
... // other modules are listed here, clipped them for brevity
github.com/gethugothemes/hugo-modules/components/social-share v0.0.0-20240925042433-d2b5d05977e8
... // other modules are listed here, clipped them for brevity
)
Because my theme uses this module, there is no actual partial file to override in my repo - it is downloaded at build time and referenced through the cache. So whilst I can see references to social-share
in my template files, I can’t edit the code. Why is that a problem? Because at time of writing, Bluesky is not available in the module.
Handily, the gettheme modules are hosted on Github, and so I know that this is the file that is used. I can grab the file and store it in the partials
directory of my site. By saving it with the same name, Hugo will override the cached version with my custom version at build time. I duplicated one block of code from the file (in this case I used the twitter block which seemed the most appropriate lol) which looks like this:
<!-- Twitter -->
{{ if $twitter }}
<a
class="share-link share-twitter"
href="https://twitter.com/intent/tweet/?text={{ .Title }}&url={{ $url }}"
target="_blank"
rel="noopener"
aria-label="share twitter">
<span aria-hidden="true" class="share-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path
d="M8 2H1l8.26 11.015L1.45 22H4.1l6.388-7.349L16 22h7l-8.608-11.478L21.8 2h-2.65l-5.986 6.886zm9 18L5 4h2l12 16z"/>
</svg>
</span>
</a>
{{ end }}
I adjusted the class
, href
, aria-label
and the svg xmlns
elements. My Bluesky equivalent looks like this:
<!-- Bluesky -->
{{ if $bluesky }}
{{ $author := printf "%s" " " | printf "%s%s" site.Params.bluesky | printf "%s%s" " by " }}
{{ $text := printf "%s" $url | printf "%s%s" $author | printf "%s%s" $text }}
<a
class="share-link share-bluesky"
href="https://bsky.app/intent/compose?text={{ $text | urlquery }}"
target="_blank"
rel="noopener"
aria-label="share bluesky">
<span aria-hidden="true" class="share-icon">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M407.8 294.7c-3.3-.4-6.7-.8-10-1.3c3.4 .4 6.7 .9 10 1.3zM288 227.1C261.9 176.4 190.9 81.9 124.9 35.3C61.6-9.4 37.5-1.7 21.6 5.5C3.3 13.8 0 41.9 0 58.4S9.1 194 15 213.9c19.5 65.7 89.1 87.9 153.2 80.7c3.3-.5 6.6-.9 10-1.4c-3.3 .5-6.6 1-10 1.4C74.3 308.6-9.1 342.8 100.3 464.5C220.6 589.1 265.1 437.8 288 361.1c22.9 76.7 49.2 222.5 185.6 103.4c102.4-103.4 28.1-156-65.8-169.9c-3.3-.4-6.7-.8-10-1.3c3.4 .4 6.7 .9 10 1.3c64.1 7.1 133.6-15.1 153.2-80.7C566.9 194 576 75 576 58.4s-3.3-44.7-21.6-52.9c-15.8-7.1-40-14.9-103.2 29.8C385.1 81.9 314.1 176.4 288 227.1z"/>
</svg>
</span>
</a>
{{ end }}
The svg xmlns
was copied directly from the fontawesome website. The href
element is using the url structure that I planned out earlier. The remaining changes are just changing Twitter references to Bluesky. The two main differences here from the Twitter equivalent is the presence of the ${{ author }}
and ${{ text }}
variables. The $author
variable is creating the text that I want to place before the url in the message, the $text
variable then appends the url. It could have been done in one line but I wanted to keep them separate for future reasons not relevant to this post.
The $text
variable is defined at the top of the template and is used by each of the different social blocks, in the Bluesky block I have adjusted it slightly so it includes my Bluesky handle. I also need to define a $Bluesky
boolean variable which is checking the dictionary that is passed to the partial. Here’s the adjusted start of the social-share partial:
{{/*
## Taken from here to customise
## https://github.com/gethugothemes/hugo-modules/blob/master/components/social-share/layouts/partials/social-share.html
*/}}
{{ $context:= .Context }}
{{ $class:= .Class }}
{{ $title:= .Title }}
{{ $facebook:= .Facebook | default false }}
{{ $twitter:= .Twitter | default false }}
{{ $email:= .Email | default false }}
{{ $bluesky:= .Bluesky | default false }}
{{ $reddit:= .Reddit | default false }}
{{ $whatsapp:= .Whatsapp | default false }}
{{ $telegram:= .Telegram | default false }}
{{ $linkedin:= .Linkedin | default false }}
{{ $pinterest:= .Pinterest | default false }}
{{ $tumblr:= .Tumblr | default false }}
{{ $vk:= .Vk | default false }}
{{ $url := printf "%s" $context.Permalink | absLangURL }}
{{ $text := printf "%s" " " | printf "%s%s" $title | printf "%s%s" "[BLOG] " }}
Setting up a Social Link
My theme manages social links (which you can see in the footer) in a data file called data/socials.json
. The one issue I had here was that the Bluesky icon would not render:
I know that my site also uses the fontawesome module from gethugothemes and on inspecting the source code for the brand.css file, there are two issues I need to fix. The first, is that it is using v6.4.2 and we need at least v6.5.2. The second is that the Bluesky icon is not listed in the css file.
My fix for these two issues is perhaps a little crude, but this is me working with my limited knowledge of external modules and overriding them. What I really want to do is override the use of the brand.css file but I can’t see how to do that. So I have simply copied the contents of the file and placed it into my custom css file, updated the url to the latest version of fontawesome and added the Bluesky icon. My custom css file looks like this:
// overrides brands.css from gethugothemes https://github.com/gethugothemes/hugo-modules/blob/master/icons/font-awesome/assets/plugins/font-awesome/v6/brands.css
:root,
:host {
--fa-font-brands: normal 400 1em/1 "Font Awesome 6 Brands";
}
@font-face {
font-family: "Font Awesome 6 Brands";
font-style: normal;
font-weight: 400;
font-display: block;
src: url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/webfonts/fa-brands-400.woff2")
format("woff2"),
url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/webfonts/fa-brands-400.ttf")
format("truetype");
}
.fab,
.fa-brands {
font-weight: 400; }
.fa-bluesky-square:before {
content: "\f081"; }
.fa-bluesky:before {
content: "\e671"; }
.fa-twitter-square:before {
content: "\f081"; }
.fa-twitter:before {
content: "\f099"; }
...
There are more icons in the code, I retained only the twitter and bluesky ones for brevity.
Observe that I have set the Bluesky content value to the unicode value of the icon (e671). I have set the font-family urls to the required version of fontawesome.
Putting it all together
- Add Bluesky handle to
params.toml
. - Add social-share.html to
partials
directory, create a Bluesky block. - Check that fa-brands is set up in your config file, if not, add it.
- Set up some custom css to override the brand.css from the fontawesome module to get a later version.
- Add a class for the Bluesky icon in the custom css.
- Update your page template to include Bluesky in the social-share partial.
Wrapping Up
Hopefully this will help you working out how to add Bluesky links and icons to your Hugo blog. I must stress, the code and config you need to change will vary depending on your theme, but this should give you a rough outline of what you need to do. It was a bit of trial and error for me, but I got there in the end! If you have any questions, or suggestions for improvement, or if you know how to handle the brand.css override more efficiently, please let me know in the comments.