Skip to main content

Eterno Devir


Logs

Brief marks and updates.


Lazy loading YouTube embeds Permalink

Since I'm adding many YouTube videos to the new Web Gems section, I decided to lazy load all YouTube embeds on the website. The concept is straightforward: instead of loading the full YouTube player for every video on a page, only the video's thumbnail and a small bit of CSS to mimic the player interface are loaded. The actual player is only requested and loaded if the reader clicks "Play". This makes pages load significantly faster and saves bandwidth. You never know if the person reading lives on a sailboat where every bit of bandwidth matters.

To achieve this, I turned to paulirish/lite-youtube-embed. It is a small JavaScript file that handles the thumbnail display and the iframe swap on play, paired with the necessary CSS for the player replica. On top of its simplicity, lite-youtube-embed uses youtube-nocookie.com by default, so no extra privacy-friendly changes were necessary. Beyond curl -O -L these two files, it was just a matter of writing a Hugo shortcode and figuring out a workaround to support playlists.

YouTube videos provide different thumbnail qualities, ranging from default to maxres. I defined maxres as default value for poster-quality, as it looks better and makes the shortcode usage a bit more ergonomic. However, a given video may not provide maxres, which requires finding the highest quality available.

For videos, the final shortcode syntax looks like this:

{{<
    lite-youtube
    src="https://www.youtube.com/watch?v=SrKj4hYic5A"
    poster-quality="sd"
>}}

For playlists, where the workaround was required, it looks like this:

{{<
    lite-youtube
    src="https://www.youtube.com/playlist?list=PLdJRJcZwR07E0CsTwSAPK-4GdQyVLvyVN"
    poster-id="eY-eyZuW_Uk"
>}}

Even though the lite-yt-embed.js and lite-yt-embed.css files are tiny (3.63 kB and 1.88 kB), it would be a waste to load them on pages without videos. So I wrote a small partial to conditionally include these two resources only when needed. That is, only pages or sections using the lite-youtube shortcode will load them.

<!-- layouts/_default/baseof.html -->
<head>
...
{{ $hasYoutube := partial "conditional-youtube.html" . }}
{{ if $hasYoutube }}
  {{ $ytCSS := resources.Get "lite-yt-embed.css" | minify | fingerprint }}
  {{ $ytJS := resources.Get "lite-yt-embed.js" | minify | fingerprint }}
  <link rel="stylesheet" href="{{ $ytCSS.RelPermalink }}" integrity="{{ $ytCSS.Data.Integrity }}" >
  <script src="{{ $ytJS.RelPermalink }}" defer integrity="{{ $ytJS.Data.Integrity }}"></script>
{{ end }}
...
</head>
<!-- layouts/partials/conditional-youtube.html -->
{{ $hasYoutube := false }}
{{ $listTypes := slice "logs" "web-gems" }}

{{ if .IsPage }}
  {{ $hasYoutube = .HasShortcode "lite-youtube" }}
{{ else if in $listTypes .Type }}
  {{ range .Paginator.Pages }}
    {{ if .HasShortcode "lite-youtube" }}
      {{ $hasYoutube = true }}
      {{ break }}
    {{ end }}
  {{ end }}
{{ end }}

{{ return $hasYoutube }}

Finally, the shortcode1 itself. As I mentioned, playlists required a small workaround. Since lite-youtube-embed expects a videoid, I manually provide one via poster-id for the thumbnail, while the shortcode handles passing the playlist ID as a parameter to the iframe.

<!-- layouts/shortcodes/lite-youtube.html -->
{{ $src := .Get "src" }}
{{ $title := .Get "title" }}
{{ $posterQuality := .Get "poster-quality" | default "maxres" }}
{{ $customParams := .Get "params" }}

{{ $url := urls.Parse $src }}
{{ $v := $url.Query.Get "v" }}
{{ $list := $url.Query.Get "list" }}

{{ if not (or $v $list) }}
  {{ erroridf "lite-youtube-invalid-url" "%s: Invalid YouTube URL: %s" .Position $src }}
{{ end }}

{{ $posterId := .Get "poster-id" | default $v }}

{{ $queryParams := dict }}
{{ with $v }}{{ $queryParams = merge $queryParams (dict "v" .) }}{{ end }}
{{ with $list }}{{ $queryParams = merge $queryParams (dict "list" .) }}{{ end }}

{{ $path := cond $list "playlist" "watch" }}
{{ $query := querify $queryParams }}
{{ $href := printf "https://www.youtube.com/%s?%s" $path $query }}

{{ $params := slice }}
{{ with $list }}{{ $params = $params | append (printf "list=%s" .) }}{{ end }}
{{ with $customParams }}{{ $params = $params | append . }}{{ end }}
{{ $params = delimit $params "&" }}

<div class="responsive-embed ratio-16-9">
  <lite-youtube
    videoid="{{ $v }}"
    title="{{ $title }}"
    poster-id="{{ $posterId }}"
    poster-quality="{{ $posterQuality }}"
    {{- with $params }}params="{{ . }}"{{- end }}>
    <a href="{{ $href }}"
       class="lyt-playbtn"
       title="{{ i18n "play" }} YouTube"
       aria-label="{{ i18n "play" }} YouTube {{ $title }}">
    </a>
  </lite-youtube>
</div>

{{ partial "nojs.html" $src }}

1

Because of the CSP rules I enforce on my website, I have since streamlined the upstream script for my use case, specifically removing the YouTube API dependency and adding direct playlist support by passing the poster-id and poster-quality attributes. The shortcode has been updated to reflect these changes.


Fatboy Slim at Elevator Music Permalink

favorites/music-videos

Although I'm pretty eclectic with music, I can count on one hand the DJs I care enough to pay closer attention. Fatboy Slim is certainly one of them. As someone who grew up with a PlayStation in the '00s, Rockafeller Skank has a very special place in my memories.

A few months ago, this set popped up in my feed, but I forgot to add it to the music video collection back then. I really enjoyed the opening and the dynamic format with the audience interacting and dancing in turns. Such a great mood.

Smiles on everyone's faces as we dance around and sing to our favorite
song... It's a secret society of misfits, artists, creative people who
are not considered normal. We are our own community. We share joy, we
share pain, we share love. For that one moment, the music connects us.

It's amazing how music can turn strangers into friends, turn anger
into happiness, and fear into power. This is truly amazing because we
are the night life.

Happy new year everyone! Do not forget to dance.


Categories in RSS feed titles Permalink

As someone who follows many RSS feeds via NNTP in Gnus, I often find myself opening some entries just to skim them and understand what they are about. This happens because some item titles alone do not provide enough context so I can act accordingly. A matter exacerbated by the fact that these entries normally fall outside my scoring rules.

In contrast, some websites prepend their content types to the article titles, helping a lot with that initial action. Rather than modifying the article titles though, this technique can be applied directly to the RSS entries. In fact, feed entries can not only differ but also be independent of the website content, which enables things like RSS-only posts.

Since I already categorize all the content here, I decided to prepend this information to the RSS item titles, leaving the article pages intact. While editing the template, I also added the <category> element as some feed readers support it. In Hugo, this was just two one-liners (formatted here for readability):

<!-- layouts/_default/rss.xml -->
<title>
  {{ with .Params.categories }}
    {{ index . 0 | lower | i18n }}:
  {{ end }}
  {{ .Title }}
</title>
<!-- layouts/_default/rss.xml -->
{{ with .Params.categories }}
  <category>
  {{ index . 0 | lower | i18n }}
  </category>
{{ end }}

I really liked how much more readable and organized the feed became with this change. It makes reasoning and acting on the entries much simpler.

For example, compare Balcony with Projects: Balcony, Essays: Balcony, or Photographs: Balcony. There is nothing wrong with the article title per se, but the labeled versions are far more informative at a glance in a feed context.

So if your website also has different post categories, go ahead and prepend them to your RSS feed titles as well. As a potential reader of your feed, I will thank you.

P.S.: Chromium users may need a different browser or, even better, a dedicated feed reader to check the results out.