メインコンテンツへスキップ

Hugoで関連記事(Related Content)を実装

·985 文字·2 分

Hugoブログを運営していると、読者に他の記事も読んでもらうために「関連記事」を表示したくなります。 CMSなどでは簡単に表示できると思うのですが、Hugoではちょっと調べる必要があり面倒でした。 今回、Hugoでの関連ページを実装したのでメモを残しておきます。

Hugoには標準で Related Content という機能がデフォルトで備わっており、複雑なコードを書かずに実装可能です。以下のコードで5記事関連ページ表示できます。ただし、文字とリンクだけで味気ないです。

layouts/partials/related.html

{{ $related := .Site.RegularPages.Related . | first 5 }}
{{ with $related }}
<h3>See Also</h3>
<ul>
 {{ range . }}
 <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
 {{ end }}
</ul>
{{ end }}

本ブログで実装しているHugoでの関連記事の実装内容を以下に記載していきます。

1. Hugoの設定ファイル (hugo.toml) の編集
#

何をもって「関連」とするかのルールを hugo.toml(または config.toml)に定義します。一般的には「同じタグ」や「同じキーワード」を持つ記事を優先させるようです。 デフォルト状態ですでに以下のように記載されていました。

[related]
  threshold = 0
  toLower = false

    [[related.indices]]
        name = "tags"
        weight = 100

    [[related.indices]]
        name = "categories"
        weight = 100

    [[related.indices]]
        name = "series"
        weight = 50

    [[related.indices]]
        name = "authors"
        weight = 20

    [[related.indices]]
        name = "date"
        weight = 10

    [[related.indices]]
      applyFilter = false
      name = 'fragmentrefs'
      type = 'fragments'
      weight = 10

2. 関連記事を表示するテンプレートの作成
#

次に、記事の下部に表示するためのパーシャルテンプレートを作成します。

例:layouts/partials/related.html

{{/* .Params.showRelated が false に設定されていない場合のみ実行 */}}
{{ if ne .Params.showRelated false }}

{{/* where関数を使って 'Section' が 'posts' のものだけを抽出 */}}
{{ $related := .Site.RegularPages.Related . }}
{{ $related = where $related "Section" "posts" | first 3 }}

{{ with $related }}
<h3 class="mt-8 text-xl font-bold">関連ページ</h3>
<div class="related-cards-container">
  {{ range . }}
  <div class="link-card-wrapper" style="margin: 15px 0; max-width: 600px;">
    <a href="{{ .RelPermalink }}" class="link-card"
      style="text-decoration: none; color: inherit; display: flex; border: 1px solid #ddd; border-radius: 8px; overflow: hidden; background: #fff; height: 110px;">

      {{/* 画像の取得ロジック */}}
      {{ $image_url := "" }}
      {{ $featured := .Resources.GetMatch "featured.webp" }}

      {{ if $featured }}
      {{/* 記事フォルダ内に featured.webp がある場合 */}}
      {{ $image_url = $featured.RelPermalink }}
      {{ else }}
      {{/* ない場合は Front Matter のパラメータを確認 */}}
      {{ $img_param := .Params.featureImage | default .Params.image }}
      {{ if $img_param }}
      {{ $image_url = $img_param | relURL }}
      {{ end }}
      {{ end }}

      {{/* 画像の表示部分 */}}
      {{ if $image_url }}
      <div class="link-card-image"
        style="flex: 0 0 140px; background-image: url('{{ $image_url }}'); background-size: cover; background-position: center;">
      </div>
      {{ else }}
      <div class="link-card-image"
        style="flex: 0 0 140px; background: #f0f0f0; display: flex; align-items: center; justify-content: center; color: #ccc;">
        No Image</div>
      {{ end }}

      <div class="link-card-content"
        style="flex: 1; padding: 12px; display: flex; flex-direction: column; justify-content: space-between; overflow: hidden;">
        <div class="link-card-title"
          style="font-weight: bold; font-size: 0.95rem; color: #333; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;">
          {{ .Title }}
        </div>
        <div class="link-card-meta"
          style="display: flex; align-items: center; gap: 8px; font-size: 0.75rem; color: #888;">
          <img src="/favicon.png" alt="" style="width: 14px; height: 14px; object-fit: contain;">
          <span>{{ .Date.Format "2006.01.02" }}</span>
        </div>
      </div>
    </a>
  </div>
  {{ end }}
</div>
{{ end }}

{{ end }}
  • サムネイルはwebp形式にしています。
  • 関連ページを表示させたくないページでは、以下のフラグで非表示にしています。
showRelated: false
nakk
著者
nakk
ITとガジェット。個人的な振り返りや技術メモを中心に投稿しています。どなたかに少しでも役立てば嬉しいです。

関連ページ