椒盐豆豉

Add random post picker to Hugo without json index

September 20, 2023
重启电脑 | English
code | project | tutorial | hugo | blog
本文总计 0.42k 字, 阅读约需要 1 分钟

I want to add a random article picker to my blog as another way to discover past posts, aside from categories and tags on the right side and making it easier on mobile.

I couldn’t find a simple enough solution that suits my needs after brief Googling. The options I found were either to randomize at build time, which means the article doesn’t change with each click or refresh, or to generate a JSON index, which I had trouble with probably because my lack of understanding of Hugo.

I thought such a simple feature should be achievable with just JS + HTML, so I decided to write my own. Performance shouldn’t be an issue for a blog with a few tens to thousands of articles. Here’s a solution I came up with for reference.

My requirements:

  • Dynamic randomization, a different article should show up with each click/refresh. (No build time randomization!)
  • Flexibile enough to use in both menu and posts.
// themes/{my-theme}/layouts/partials/docs/random.html
<script>
  function goToRandomPost() {
    const pages = [
      {{ range ((where .Site.RegularPages "Type" "post")) }}
      "{{ .RelPermalink }}?utm_source=random",
      {{ end -}}
    ];
    const rand = Math.floor(Math.random() * pages.length);
    window.location.href = pages[rand];
  }
</script>
<a class="random" onclick='goToRandomPost()'>Feeling lucky?</a>

I got lazy and directly modified the window location as redirect. If you need more data to render post info, change window.location row according to your needs. Just standard JS won’t expand here.

For the shortcode version of the script is exactly the same. The rendering part has two additional parameters for customization. The first one controls the displayed text, and the second controls whether it’s a link or button.

// themes/{my-theme}/layouts/shortcodes/random.html
{{- if eq (index .Params 1) "button"}}
  <a onclick='goToRandomPost()' class="book-btn">{{ index .Params 0}}</a>
{{- else -}}
  <a onclick='goToRandomPost()' style="cursor: pointer;">{{ index .Params 0}}</a>
{{- end -}}

Compared to the JSON index generation version that ranks high in Google search results([1][2]), this solution has the following advantages for me IMO:

  1. More flexible and simpler to set up. No need to debug different template configs, just copy and paste these two files and it’s good to go.
  2. The logic is easy to modify and you can see the changes immediately without regenerating the index.
  3. It’s more expandable feature wise, such as adding the number of posts, recommending related posts within the same tag, etc.

Now that you’re here: Pick the next post for me

Read Chinese version of this post here.

en >}}

相关阅读


<< prev | 给 Hugo 博客添加随机文章... Feeling Lucky 个人年度游戏编年史 | next »

If you find this blog useful and want to support my blog, need my skill for something, or have a coffee chat with me, feel free to:

Become Patreon Buy me a boba