Bypass blocking of embedded tweets using Hugo shortcodes

Bypass blocking of embedded tweets using Hugo shortcodes

Table of Contents


I knew this was coming but hadn’t got round to fixing it and now my site is failing to build. The error in github actions is;

Start building sites … 
hugo v0.112.5-48e33e10af2feb2a0e1c32d04880ed016619f2d8+extended linux/amd64 BuildDate=2023-05-29T07:27:36Z VendorInfo=gohugoio
ERROR 2023/08/24 08:14:38 **Failed to get JSON resource "**": Failed to retrieve remote file: Forbidden, body: "{\"error\":\"Sorry, you are not authorized to see this status.\",\"request\":\"\\/oembed?dnt=false&\"}"
If you feel that this should not be logged as an ERROR, you can ignore it by adding this to your site config:
ignoreErrors = ["error-remote-getjson"]
Total in 1565 ms

Stupid Xwitter.

How did Twitter shortcodes work?

Historically, Hugo had a built-in shortcode that you could call using the notation tweet user=(user) id=(id) where the user is the username of the twitter user and the ID is the ID of the specific tweet which you can find in the Twitter URL. Here is the ID;

Shows a tweet whose URL is, the ID is the number part: 1664934219783471104

Hugo would convert this into a HTML block that would be rendered as a tweet. This was really useful and I used it a lot.

How to resolve

So now that it no longer works, I am faced with a lot of broken posts. I need to remove all the embedded tweets and replace them with fixed images. I am not going to be able to avoid doing the screenshot work but I don’t really want to change all the posts. Hugo has a template order that prioritises custom content over built-in content. What I wanted to try (and spoiler alert…it works!) is if I create a shortcode with the same name as the built-in shortcode, it will override it. I can then use this shortcode to produce an image rather than the embedded tweet.

The plan

The tweet shortcode uses two arguments - user and ID so I need to utilise them in my shortcode to avoid breaking my code. So the plan is to store each tweet with the id as the filename so I can construct an image URL using that ID. As for the username, I don’t need it, but I will use it to produce some alt text.

The images

I need to grab screenshots of all the tweets, this is the only manual bit I can’t really avoid. I am going to store them in my static folder in a folder called tweets. I am going to use the tweet ID as the filename. That looks like this;

Shows the file structure of my site in Visual Studio Code, static/tweet directory is open and shows multiple images all named with their tweet ID

The shortcode

In my layouts folder, I will create a tweet.html file which will look like this;

{{ $id := .Get "id" }}
{{ $user := .Get "user" }}

<a href="{{$user}}/status/{{$id}}" target="_blank">
    {{ with $id }}
      <source srcset="{{ $.Site.BaseURL }}/tweets/{{$id}}.png">
      <img src=posts/2023/shortcodes-to-the-rescue-twitter-embedded-tweet-failure/"{{ $.Site.BaseURL }}/tweets/{{$id}}.png" alt="Image is of a tweet by {{$user}} click on the image to read the original tweet" defer class="lazyautosizes lazyloaded" data-sizes="auto" data-src=posts/2023/shortcodes-to-the-rescue-twitter-embedded-tweet-failure/"{{ $.Site.BaseURL }}/tweets/{{$id}}.png" >

So all I have done here is added an <img> tag and constructed the image URL based on the ID parameter and my site’s URL parameter. Any content in the static folder gets pushed to the root during build so static/tweets/{id}.png becomes {url}/tweets/{id}.png. I have also wrapped the image in an <a> tag so that I can create a hyperlink back to the original tweet based on my arguments. The point being that having laid out everything consistently, it should just work. In time I will add an $alt parameter to my shortcode so that I can give each image specific alt text but this serves to get my site back up and running a little quicker and at the very least provides some context for screen readers.

The test

So now I can run a local build and cross my fingers…

The output of the build is displayed, the Web Server has returned the local url which means that the site appears to have built

It looks like it worked! Final test is to check a post on my local site to see if it really did work;

A snippet from the Unplugging page showing an image of a tweet by Josh Duffney that says How I went from aimless to an SRE at StackOverflow in less than a year below it is the alt text that reads Image is of a tweet by joshduffney click on the image to see the tweet

It all worked #VictoryDance! I can now commit this change and push it to github and the build should pass.


Shortcodes are a really cool way of applying custom content to your site consistently. I didn’t realise you could override a built-in one but this test seems to prove you can. This has saved me quite a bit of time restructuring several posts. I continue to love Hugo!


Recent Posts