A simple Hugo shortcode for embedding Bluesky posts

While it doesn’t do static embeds, this shortcode gives you an easy way to show content from an increasingly popular social network.

2024-11-13

The Bluesky social media network, initially hampered by a wait-for-your-invite policy while capacity was being enhanced, recently has hit a growth spurt. Bluesky is now getting increasing attention from not only individual users but also a variety of larger entities, including a number of major sites which have been leaving Twitter/X for hoped-to-be-greener pastures. This post gives you a simple Hugo shortcode for embedding Bluesky posts in your content.

I shamelessly based this shortcode, called bluesky, on Hugo’s existing twitter shortcode for embedding Twitter/X content through the oEmbed protocol, which Bluesky also uses. Please note:

  • Bluesky’s use of oEmbed is somewhat more limited than what works with Hugo’s twitter. This document explains what Bluesky’s oEmbed endpoint recognizes.
  • This is not a static embed, such as those about which I originally wrote in 2022 regarding content from Twitter (before I had to deprecate my articles on the subject due to Twitter’s later closing off the applicable API) and Mastodon. Fortunately, at least as of this writing, there apparently is no tracking code within what this embed downloads to a browser. The embed does, however, require JavaScript to look normal.1

Using the bluesky shortcode

The bluesky shortcode takes only one parameter: link for the URL of the Bluesky post you want to embed. Here is an example of the bluesky shortcode in use2:

{{< bluesky link="https://bsky.app/profile/bsky.app/post/3latotljnec2h" >}}

. . . which produces the following:

15M people on Bluesky!!! 💫 The Verge beat us to our own announcement — that's the beauty of an open network with public stats!

Bluesky (@bsky.app) 2024-11-13T15:43:47.612Z

The code

bluesky.html

{{- $link := .Get "link"  -}}
{{- $query := querify "url" $link -}}
{{- $request := printf "https://embed.bsky.app/oembed?%s" $query -}}

{{- $jsonOembed := resources.GetRemote $request -}}
{{- $jsonOembed = $jsonOembed | transform.Unmarshal -}}
{{- $jsonOHTML := $jsonOembed.html -}}
{{- $jsonOHTML | safeHTML -}}

  1. If the embed appears without JavaScript running, you’ll see a bare-bones, text-only representation which, actually, is very similar to how the Hugo twitter shortcode handles tweets if you have Hugo’s privacy settings set appropriately — and, in fact, that may be preferable to those who are likely to disable JavaScript in their browsers. ↩︎

  2. If you happen upon this site’s repo out of curiosity and check out this post’s Markdown file, you’ll notice that this example’s curly-bracketed boundaries also have wrapping /* and */, respectively. That’s because, otherwise, Hugo sees it as real code, not just a representation of it, and acts accordingly — in this case, once again displaying the image. See “Highlight Hugo/GO Template Code” in the Hugo documentation. ↩︎

Reply via email
View comments