What is the best place to add Scratch for every page?

Hello All.

First of all many thanks for creating and supporting Hugo.

I am having some troubles with understanding the processing order of Hugo.

Basically I have a bit of code which should be ran once - at the very beginning of the Hugo build.
It has to process each page and add some data to that page’s Scratch:

{{/* process every page */}}
{{ range .Site.Pages }}
	{{/* partial which adds some data to the page's scratch */}}
	{{ partial "page/get-version-info" . }}
{{ end }}

I tried adding this to the theme’s /index.html but I noticed that not every page has the expected Scratch when processing them in their layout files (single.html, list.html etc).

What would be the best file to place this piece of code so that it is executed before processing any of the other layout files?

old blog

HTH

It’s been discussed before (and I’m sure someone will dig up the link and put below :-)):

  • One of the reasons Hugo is so fast is that we do lot of parallel processing.
  • We do, however, render the output formats serialized and in a deterministic order.
  • So, what you can do is to define a custom output format with a template for the home page that collect this info and define that to be the first one (by setting the weight).

I solved this using a cached partial, and limiting the number of goprocesses to 1.

Thanks for all the tips. I will play with it next couple of evenings and report back.

I created this repository to test four ways to run the partial which adds the Scratch data:

  1. Using a loop in the home page layout (demo).
  2. Using a loop in a custom output layout for the home page (demo).
  3. As the page is processed by its corresponding layout (demo).
  4. Using a loop in a custom layout, which is used by a dedicated content page (demo). This page has the weight set such that it will be processed first.

Results

The last one (customLayout) gave the best results. It uses a markdown file to run the custom layout. By setting the _build options in the front matter the file itself doesn’t get rendered.

Markdown file

run-custom-layout.md:

---
title: Run custom layout
layout: custom-layout
weight: -9999

_build:
  render: always
  list: never
---

Layout file

_default/custom-layout.html:

{{/* custom layout to process scratch for each page */}}
{{ if eq (.Param "scratchProcessing") "customLayout" }}
  {{ $total := newScratch }}
  {{ $total.Add "total" 1 }}
  {{ range .Site.Pages }}
    {{ partial "add-scratch" (dict "ctx" . "order" ( $total.Get "total" )) }}
    {{ $total.Add "total" 1 }}
  {{ end }}
  {{ warnf "\n\n  --> scratch added to %v pages by custom-layout" ($total.Get "total") }}
{{ end }}

Partial for adding the scratch data

partials/add-scratch.html:

{{ with .order }}
  {{ $.ctx.Page.Scratch.Set "myScratch" (dict "number" .) }}
{{ else }}
  {{ $.ctx.Page.Scratch.Set "myScratch" (dict "number" (substr (now.UnixNano) 10 -4 ) ) }}
{{ end }}

Thoughts

Using this approach the scratch data is available for most pages (in both page title and -very important- the recursive sidebar), but sometimes the sidebar still lacks a number here and there.

Any idea how I can make this more solid?