Update Hugo Tweet Shortcodes with PowerShell, Curl, and the Twitter API

How to update Hugo Tweet Shortcodes to include the user and id parameters.


If, like me, you are using the Hugo static site generator for your website you may have noticed the following error message appearing in your build console recently.

1The "tweet" shortcode will soon require two named parameters: user and id.


1The "twitter" shortcode will soon require two named parameters: user and id.


You can (currently) add a shortcode link to a tweet using just the ID number of the tweet, for example:

1{{< tweet 1332331305154076678 >}}

However this shortcode format will soon stop working and needs to be replaced with a syntax including the ID of the tweet and the handle of the twitter user, for example:

1{{< tweet id="1332331305154076678" user="isjwuk" >}}

Which would render in the published site something like:

Full details of the reasoning for the change are documented in the Hugo repository on github.com, but in summary it was a change to the upstream endpoint used by the shortcode and there is an interim behaviour that means the old format shortcodes continue to work for now.

The existing endpoint requires a single parameter: the id of the tweet.

The new endpoint requires two parameters: the id of the tweet, and the user with whom it is associated. For the moment, if you supply the wrong user, the request will be redirected (with a small delay) to the correct user/id pair. This behavior is undocumented, but we will take advantage of it as Hugo site authors transition to the new syntax.

Source github.com/gohugoio Nov 1, 2021


A site can have many, many embedded tweets and it could take a long time to go through each one manually updating. I updated my sites with the following mix of PowerShell, curl, and the Twitter API.

To start, you will need a Twitter Developer account to access the API. These are free, and you can sign up on developer.twitter.com. At the end of the application process you create a project and app, go through this process and note down the keys and tokens it gives you. The important token needed for this code is the “Bearer Token”.

Next take a copy of your site to work on, ideally you’d be creating a new branch for this from your repository. This is so you can roll back when something goes wrong.

Here is the PowerShell code. Configure the two variables at the top to point at your Hugo source code and include your Bearer Token from above.

 4#Function to use Twitter API to convert a Tweet ID to a Twitter Handle
 5Function Get-TwitterHandleFromTweetID ([string]$TweetID, [string]$BearerToken){
 6	$URL="https://api.twitter.com/2/tweets/"+$TweetID+"?expansions=author_id"
 7	(curl -X GET -H "Authorization: Bearer $BearerToken" "$URL"  2>(New-TemporaryFile)  | ConvertFrom-Json).includes.users.username
 9#Define what our current shortcode starts with 
10$shortcode="{{"+"< tweet "
11#Get all the Markdown files in the Hugo folder
12$files=Get-ChildItem $DIR -Filter "*.md" -Recurse
13#Loop through the files
14Foreach ($file in $Files.fullname) {
15  #Reset our Changed flag to false, until we make any changes to this file.
16  $changed=$false
17  #Get Lines in file containing Tweet shortcodes that we haven't yet updated
18  $Content=Get-Content $file
19  Foreach ($Tweetcode in (get-content $file.Split("`n")| Where {$_.Startswith($shortcode) -and $_ -notlike "*user=*"})) { 
20    #Extract the Tweet ID from the shortcode
21	  $TweetID=($Tweetcode -split $shortcode -split " >}}")[1]
22	  #Get TwitterHandle from Tweet ID
23	  $TwitterHandle=Get-TwitterHandleFromTweetID -TweetID $TweetID -BearerToken $BearerToken
24	  #Update the shortcode in the file content
25		$Content=$Content.Replace($shortcode+$TweetID, $shortcode+'id="'+$TweetID+'" user="'+$TwitterHandle+'"')
26    #Set our Changed flag to true as we've changed the file content
27	  $changed=$true
28  }
29  #Update file if changes were made.
30  If ($changed){
31    #Write the updated file
32    $Content > $file 
33    #Make a note on the console that we've done this
34    "Updated $file" 
35  }

Finally you can check by running your local Hugo server and confirming that the warning messages no longer appear.

1hugo server