HUGO
News Docs Themes Community GitHub

Related content

List related content in “See Also” sections.

Hugo uses a set of factors to identify a page’s related content based on front matter parameters. This can be tuned to the desired set of indices and parameters or left to Hugo’s default related content configuration.

To list up to 5 related pages (which share the same date or keyword parameters) is as simple as including something similar to this partial in your template:

layouts/partials/related.html
{{ with site.RegularPages.Related . | first 5 }}
  <p>Related content:</p>
  <ul>
    {{ range . }}
      <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
    {{ end }}
  </ul>
{{ end }}

The Related method takes one argument which may be a Page or an options map. The options map has these options:

indices
(slice) The indices to search within.
document
(page) The page for which to find related content. Required when specifying an options map.
namedSlices
(slice) The keywords to search for, expressed as a slice of KeyValues using the keyVals function.
fragments
(slice) A list of special keywords that is used for indices configured as type “fragments”. This will match the fragment identifiers of the documents.

A fictional example using all of the above options:

{{ $page := . }}
{{ $opts := dict
  "indices" (slice "tags" "keywords")
  "document" $page
  "namedSlices" (slice (keyVals "tags" "hugo" "rocks") (keyVals "date" $page.Date))
  "fragments" (slice "heading-1" "heading-2")
}}

We improved and simplified this feature in Hugo 0.111.0. Before this we had 3 different methods: Related, RelatedTo and RelatedIndices. Now we have only one method: Related. The old methods are still available but deprecated. Also see this blog article for a great explanation of more advanced usage of this feature.

Index content headings

Hugo can index the headings in your content and use this to find related content. You can enable this by adding a index of type fragments to your related configuration:

related:
  includeNewer: true
  indices:
  - applyFilter: true
    name: fragmentrefs
    type: fragments
    weight: 80
  threshold: 20
  toLower: false
[related]
  includeNewer = true
  threshold = 20
  toLower = false
  [[related.indices]]
    applyFilter = true
    name = 'fragmentrefs'
    type = 'fragments'
    weight = 80
{
   "related": {
      "includeNewer": true,
      "indices": [
         {
            "applyFilter": true,
            "name": "fragmentrefs",
            "type": "fragments",
            "weight": 80
         }
      ],
      "threshold": 20,
      "toLower": false
   }
}
  • The name maps to a optional front matter slice attribute that can be used to link from the page level down to the fragment/heading level.
  • If applyFilter is enabled, the .HeadingsFiltered on each page in the result will reflect the filtered headings. This is useful if you want to show the headings in the related content listing:
{{ $related := .Site.RegularPages.Related . | first 5 }}
{{ with $related }}
  <h2>See Also</h2>
  <ul>
    {{ range $i, $p := . }}
      <li>
        <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
        {{ with .HeadingsFiltered }}
          <ul>
            {{ range . }}
              {{ $link := printf "%s#%s" $p.RelPermalink .ID | safeURL }}
              <li>
                <a href="{{ $link }}">{{ .Title }}</a>
              </li>
            {{ end }}
          </ul>
        {{ end }}
      </li>
    {{ end }}
  </ul>
{{ end }}

Configuration

See configure related content.