HUGO
Menu
GitHub 89737 stars Mastodon

Configure related content

Configure related content.

Use the Pages.Related method to render related content in your templates.

Hugo provides a sensible default configuration for identifying related content, but you can customize it in your project configuration, either globally or per language.

Default configuration

This is the default configuration:

related:
  includeNewer: false
  indices:
  - applyFilter: false
    cardinalityThreshold: 0
    minTokenLength: 0
    name: keywords
    pattern: ''
    toLower: false
    tokenize: false
    type: basic
    weight: 100
  - applyFilter: false
    cardinalityThreshold: 0
    minTokenLength: 0
    name: date
    pattern: ''
    toLower: false
    tokenize: false
    type: basic
    weight: 10
  - applyFilter: false
    cardinalityThreshold: 0
    minTokenLength: 0
    name: tags
    pattern: ''
    toLower: false
    tokenize: false
    type: basic
    weight: 80
  threshold: 80
  toLower: false
[related]
  includeNewer = false
  threshold = 80
  toLower = false
  [[related.indices]]
    applyFilter = false
    cardinalityThreshold = 0
    minTokenLength = 0
    name = 'keywords'
    pattern = ''
    toLower = false
    tokenize = false
    type = 'basic'
    weight = 100
  [[related.indices]]
    applyFilter = false
    cardinalityThreshold = 0
    minTokenLength = 0
    name = 'date'
    pattern = ''
    toLower = false
    tokenize = false
    type = 'basic'
    weight = 10
  [[related.indices]]
    applyFilter = false
    cardinalityThreshold = 0
    minTokenLength = 0
    name = 'tags'
    pattern = ''
    toLower = false
    tokenize = false
    type = 'basic'
    weight = 80
{
   "related": {
      "includeNewer": false,
      "indices": [
         {
            "applyFilter": false,
            "cardinalityThreshold": 0,
            "minTokenLength": 0,
            "name": "keywords",
            "pattern": "",
            "toLower": false,
            "tokenize": false,
            "type": "basic",
            "weight": 100
         },
         {
            "applyFilter": false,
            "cardinalityThreshold": 0,
            "minTokenLength": 0,
            "name": "date",
            "pattern": "",
            "toLower": false,
            "tokenize": false,
            "type": "basic",
            "weight": 10
         },
         {
            "applyFilter": false,
            "cardinalityThreshold": 0,
            "minTokenLength": 0,
            "name": "tags",
            "pattern": "",
            "toLower": false,
            "tokenize": false,
            "type": "basic",
            "weight": 80
         }
      ],
      "threshold": 80,
      "toLower": false
   }
}

Adding a related section to your project configuration requires you to provide a full configuration. You cannot override individual default values without specifying all related settings.

Top-level settings

threshold
(int) A value in the range [0, 100]. A lower value will return more, but maybe not so relevant, matches.
includeNewer
(bool) Whether to include pages newer than the current page in the related content listing. The output for older posts may change as new related content is added. Default is false.
toLower
(bool) Whether to transform keywords in both the indexes and the queries to lower case. This may give more accurate results at a slight performance penalty. Default is false.

Per-index settings

applyFilter
(bool) Apply a type specific filter to the result of a search. This is only used for the fragments type. Default is false.
cardinalityThreshold
(int) The percentage threshold, in the range [1, 100], above which indexed values are removed from the index. For example, a value of 60 removes all indexed values that appear in more than 60% of the documents. A value of 0 disables filtering. Default is 0.
minTokenLength
New in v0.166.0
(int) When tokenize is true, the minimum token length in Unicode code points. Use this to exclude short words such as a, in, and the, regardless of their frequency. This setting is applied before cardinalityThreshold, so excluded tokens never enter the index. Default is 0, meaning no minimum.
name
(string) The index name. This value maps directly to a page parameter. Hugo supports string values such as author, lists such as tags and keywords, and time and date objects.
pattern
(string) This is only relevant for dates. When listing related content, you may want to list content that is also close in time. Setting 2006, the default value for date indexes, as the pattern for a date index will add weight to pages published in the same year. For busier blogs, 200601, representing year and month, may be a better default.
tokenize
New in v0.166.0
(bool) Whether to tokenize string values by splitting on whitespace before indexing.

For indices of type fragments, non-heading fragments such as description list terms are always indexed by their exact identifier.

Tokenizing increases index size in proportion to the number of words per value. Consider setting minTokenLength to exclude short words and cardinalityThreshold to remove high-frequency words from the index.

Singular and plural forms such as apple and apples are treated as distinct words, and CJK languages and other scripts without whitespace word boundaries are not supported.

Default is false.

toLower
(bool) Whether to transform keywords in both the indexes and the queries to lower case. This may give more accurate results at a slight performance penalty. Default is false.
type
(string) One of basic or fragments. Default is basic.
weight
(int) An integer weight that indicates how important this parameter is relative to the other parameters. It can be 0, which has the effect of turning this index off, or even negative. Test with different values to see what fits your content best. Default is 0.

Examples

The following examples demonstrate common configuration patterns.

Imagine we’re building a book review site. Our main content will be book reviews, and we’ll use genres and authors as taxonomies. When someone views a book review, we want to show a short list of related reviews based on shared authors and genres.

Create the content:

content/
└── book-reviews/
    ├── book-review-1.md
    ├── book-review-2.md
    ├── book-review-3.md
    ├── book-review-4.md
    └── book-review-5.md

Configure the taxonomies:

taxonomies:
  author: authors
  genre: genres
[taxonomies]
  author = 'authors'
  genre = 'genres'
{
   "taxonomies": {
      "author": "authors",
      "genre": "genres"
   }
}

Configure the related content identification:

related:
  includeNewer: true
  indices:
  - name: authors
    weight: 2
  - name: genres
    weight: 1
  threshold: 80
  toLower: true
[related]
  includeNewer = true
  threshold = 80
  toLower = true
  [[related.indices]]
    name = 'authors'
    weight = 2
  [[related.indices]]
    name = 'genres'
    weight = 1
{
   "related": {
      "includeNewer": true,
      "indices": [
         {
            "name": "authors",
            "weight": 2
         },
         {
            "name": "genres",
            "weight": 1
         }
      ],
      "threshold": 80,
      "toLower": true
   }
}

We’ve configured the authors index with a weight of 2 and the genres index with a weight of 1. This means Hugo prioritizes shared authors as twice as significant as shared genres.

Then render a list of 5 related reviews with a partial template like this:

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 }}

Imagine we’re building a blog. We want to show related posts based on shared words in the title. For example, a post titled “Hugo image processing” should match any post whose title contains Hugo, image, or processing.

Configure the related content identification:

related:
  indices:
  - minTokenLength: 4
    name: title
    tokenize: true
    weight: 1
  threshold: 50
  toLower: true
[related]
  threshold = 50
  toLower = true
  [[related.indices]]
    minTokenLength = 4
    name = 'title'
    tokenize = true
    weight = 1
{
   "related": {
      "indices": [
         {
            "minTokenLength": 4,
            "name": "title",
            "tokenize": true,
            "weight": 1
         }
      ],
      "threshold": 50,
      "toLower": true
   }
}

With tokenize set to true, Hugo splits each page title on whitespace and indexes the individual words. Setting minTokenLength to 4 excludes short words such as and, the, and for. Then use the same partial template shown in the previous example to render the results.