Setting page params/variables from a template

Is it possible to overerride the value of a site param for a specific page usign a template and/or define (and initialize) a custom page parameter from a template (namely, a layout template)? The parameter value would also need to be accessible from shortcodes.

Yes, you can override Site Parameters in a template or front matter and you should be able to access the new parameters from shortcodes. There are several threads in the forum.

But what are you trying to do? Give us a more concrete example.

What is the syntax for overriding a site/page parameter value in a template? I searched the discourse threads but I didn’t find a working code syntax.

This is my incentive: we used Hugo to create a documentation site that has some versioned content. For reasons that I will not go into, the content for the different versions is currently saved in the same GitHub branch. Versioned site sections have latest-release/ and vX.Y/ directories (e.g., v1.0/). We have global site variables (params) for storing the latest version number and all supported version numbers. We also have a shortcode to return the latest produt version number, which we use in the MD content files.
Because Hugo requires unique navigation-menu page identifiers across the site, we also had to use latest-release or <version> in the menu.main identifier and parent key values of each page.

When we release a new version, we would need to duplicate the current latest-release/ directory to a new vX.Y/ directory, and replace all version-number references that are intended to refer to the “active” version of the ancestor version directory, both in the front matter and in the content. We could do this with a script, which is our current plan, but I was hoping there was a way to handle this with Hugo. This was my thought:

  • Define a global product-version site param / data param that will be initialized to the latest version number.
  • In the layout template files, identify if the current page is a descendant of a /vX.Y/ directory (which we can do by parsing the page URL), and if so, override the version-number param configuration for the specific page. In addition, the pages would set identifierBase and parentBase params, and the layout will define the params for the page by appending -<version> to the configured base number.
  • Define a product-version shortcode that returns the page’s configured version number, or the default global site configuration if there is no unique page configuration.

This way, we should be able to simply copy an existing <doc section>/latest-release/ directory to a <doc section>/vX.Y/ directory and the page menu IDs and active-version shortcode references will all be updated automatically (via the template) to match the version number set in the ancestor version directory, without the need for any manual or scripting editing of the pages. But this design requires the ability to update page params from the layout template, which I wasn’t able to do far. So for the time being, I’m going with a scripting solution that will configure the version number in the front matter of each page in a new versioned-content directory to override global site configurations (and I can still have an active-version shortcode that returns either the page version configuration or the global site configuration if the former doesn’t exist, so there would be no need to edit the MD content). We would also need to update our cross-reference shortcode so that veresioned-content references will refer to the pages for the active version.

This should help you

{{ if eq .Section "vX.Y" }} <----- override global version site param ----->{{ end }}

Note that this will affect all pages in this section.

As for getting the parameter through a shortcode I’ve only had a need to do this from the first parent page.

So I haven’t tried going higher up.

But someone else has tried. See: Nested Shortcodes - Get Furthest/Farthest Parent Param


Actually, I don’t think {{ if eq .Section "vX.Y" }} will help us because the root section directories aren’t versioned. They have child version subdirectories. However, we think we can bypass this hurdle by parsing the page URL. What we don’t know is how to do the “override global version site param” part.
I’m still stuck with the following issue: because menu IDs need to be unique across a doc section, and we have multiple version subdirectories in each section, we need to use a version ID in the main-menu identiifer and parent values (which we configure in the page’s front matter). Now, if we create a new vX.Y/ directory from a latest-release/ directory when a new version is released, we need to edit all the main-menu identifier and parent front-matter configurations in the new directory. If we could set these values from a template, we could use custom front-matter params to set the unique non-versioned values, and append the version number to create the identifier and parent values, but we don’t know how to set these values from a template (we only know how to set them directly in the front matter) … .

I looked at the thread that you mentioned — Nested Shortcodes - Get Furthest/Farthest Parent Param. It looks interesting but it’s a bit complex for me to understand right of the bat. I’ll need to study it more thoroughly when I have the time. I’m not sure it will help me with this specific issue, but it might be useful for other tasks.

In that case why don’t you try to set a front matter parameter with the version number in the of your nested sections. Then you should be able to render this param with something like:

 {{- if .Sections -}}
 {{- range .Sections -}}
 {{- range $i, $e := .Data.Pages -}}
 {{- with .Params.version -}}{{ . }}{{- end -}}
 {{- end -}}
 {{- end -}}
 {{- end -}}

Also a simple way to get this param in other places of your site is .GetPage

I thought of setting the version number in the root index page of the versioned directory as well, but I didn’t know how to identify the ancestor version directory of the current page. Consider an xxx/ section diretory with v1.0/ and V1.1/ subdirectories, each setting the version number in their root index page. From within a page in one of the version subdiretories, how would you know which index-page version configuration applies ot the current page. But as I wrote, I believe we already found another solution to this problem, which is by extracting the version number from the page’s URL. Another developer did he a POC, which I have not tested yet but I understood from him that it works.
We still don’t have a solution, though, for setting unique version-specific main-menu IDs from the Hugo code, without having to manually edit the values in the front matter of each page — because we don’t know how to set a page’s main-menu idenitifer, for example, from a template.

Hi Sharoni,

After reading what your trying to do, change the menu identifier when you archive a latest version in a new section. I do not think that is possible to change a parameter from within a template. I believe they are gathered and organized by the system prior to templates being rendered. Hugo team would have to make some sort of function to change that in the backend, which might be impossible as other templates have already processed.

Instead of addressing the problem from the parameter side could you adjust your approach from the menu side?

Circumvent the hugo menu system (static) and build your menus yourself from the section structure dynamically in templates using the content’s structure?

This way you don’t get errors for having duplicate identifiers in the menu object/map. Then as you change your content’s section structure to include a deprecated version the custom section menu you create would update to reflect your content structure not a static menu structure.

Side Note:
I don’t think the “Nested Shortcodes - Get Furthest/Farthest Parent Param” will help, this is used to grab parent parameters from nested shortcodes. If you need any help using this partial/function I would be glad to answer questions. It’s pretty easy to set up and use, it’s just the code inside the partial is the complex part. But I don’t think it applies to your current problem.

Thought maybe that would help…