The Never-Ending Confusion over Variables

Well, since the advent of 0,13 has had me tinkering with my templates again, I’m afraid it’s back to headbutting walls in confusion with regard to trying to understand Hugo’s variables [both config and template]. Might as well flag the issue up again, since the new release is likely to be sending some traffic this way.

Much though I love Hugo, I’m afraid I find the documentation pretty opaque when it comes to accessing the various [pun intended!] variables… some seem to work with just {{ .varname }}, some need {{ .Site.varname }}, others need {{ .Data.varname }} or, {{ .Site.Params.varname }}, or just {{ .Params.varname }} or various combinations of all of those [and that’s without even mentioning the fact that some vars seem to be defined/referred to in some places using an initial capital letter and in others using all lower case].

Now I realise that this is because of the different scopes of the different variables and I’m prepared to wrestle with the complexities of that, but I think it would really help if someone on the project team could be charged with improving the documentation to make things a bit more explicit.

Here’s a concrete example of what I mean:

Flushed with the success of having just added pagination to my site, I thought I’d also add PREV and NEXT links inside my individual article pages too. So I fired up the Documentation and looked at the [Template Variables][1] page.

Under the section titled Page Variables, we see the following:

Page Variables

.Title The title for the content.
.Content The content itself, defined below the front matter.
.Summary A generated summary of the content for easily
showing a snippet in a summary view. Note that the breakpoint can be set
manually by inserting at the appropriate place in the content page. See Summaries for more details.
.Truncated A boolean, true if the .Summary is truncated. Useful for showing a “Read more…” link only if necessary. See Summaries for more details.
.Description The description for the content.
.Keywords The meta keywords for this content.
.Date The date the content is associated with.
.PublishDate The date the content is published on.
.Type The content type (e.g. post).
.Section The section this content belongs to.
.Permalink The Permanent link for this page.
.RelPermalink The Relative permanent link for this page.
.LinkTitle Access when creating links to this content. Will use linktitle if set in front matter, else title.
.Taxonomies These will use the field name of the plural form of the taxonomy (see tags and categories below).
.RSSLink Link to the taxonomies’ RSS link.
.TableOfContents The rendered table of contents for this content.
.Prev Pointer to the previous content (based on pub date).
.Next Pointer to the following content (based on pub date).
.PrevInSection Pointer to the previous content within the same section (based on pub date)
.NextInSection Pointer to the following content within the same section (based on pub date)
.FuzzyWordCount The approximate number of words in the content.
.WordCount The number of words in the content.
.ReadingTime The estimated time it takes to read the content in minutes.
.Weight Assigned weight (in the front matter) to this content, used in sorting.
.IsNode Always false for pages.
.IsPage Always true for page.
.Site See Site Variables below.
.Hugo See Hugo Variables below.

So I tried adding {{.Prev}} and {{.Next}} links into my single.html template and hugo server crapped out with a nil pointer error on one of the links and a 404 on the other. So, having been here before when working with vars in Hugo and just out of interest, I decided to output all the abovelisted page variables onto my pages, just to see what is actually being generated. So I made a quick HTML list and embedded it in the single.html template:

<li>TITLE: {{.Title}}</li>
<li>CONTENT: {{.Content}}</li>
<li>SUMMARY: {{.Summary}}</li>
<li>TRUNCATED: {{.Truncated}}</li>
<li>DESCRIPTION: {{.Description}}</li>
<li>KEYWORDS: {{.Keywords}}</li>
<li>DATE: {{.Date}}</li>
<li>PUBLISHDATE: {{.PublishDate}}</li>
<li>TYPE: {{.Type}}</li>
<li>SECTION: {{.Section}}</li>
<li>PERMALINK: {{.Permalink}}</li>
<li>RELPERMALINK: {{.RelPermalink}}</li>
<li>LINKTITLE: {{.LinkTitle}}</li>
<li>TAXONOMIES: {{.Taxonomies}}</li>
<li>RSSLINK: {{.RSSLink}}</li>
<li>TABLEOFCONTENTS: {{.TableOfContents}}</li>
<li>PREV: {{.Prev}}</li>
<li>NEXT: {{.Next}}</li>
<li>PREVINSECTION: {{.PrevInSection}}</li>
<li>NEXTINSECTION: {{.NextInSection}}</li>
<li>FUZZYWORDCOUNT: {{.FuzzyWordCount}}</li>
<li>WORDCOUNT: {{.WordCount}}</li>
<li>READINGTIME: {{.ReadingTime}}</li>
<li>WEIGHT: {{.Weight}}</li>
<li>ISNODE: {{.IsNode}}</li>
<li>ISPAGE: {{.IsPage}}</li>
</ol>````

I reloaded *hugo server* and got the following displayed on the page:

````1. TITLE: Brothword 0001
2. CONTENT:  <snip>
3. SUMMARY: blah...blah...blah...
4. TRUNCATED: true
5. DESCRIPTION: 
6. KEYWORDS: []
7. DATE: 2015-02-23 15:26:51 +0000 
8. UTCPUBLISHDATE: 0001-01-01 00:00:00 +0000 UTC
9. TYPE: post
10. SECTION: 
11. PERMALINK: http://localhost:1313/2015-02-13-brothword0001/
12. RELPERMALINK: /2015-02-13-brothword0001
13. LINKTITLE: Brothword 0001
14. TAXONOMIES:````

Not too bad so far, although some of the variables seem to be empty, even though they should have values [eg. `.Keywords`]. But why does the list stop at no. 14? A quick check of hugo server's output shows:

```ERROR: 2015/02/28 Error while rendering page ....  executing "theme/_default/single.html" at <.Taxonomies>: Taxonomies is not a field of struct type *hugolib.Page````

OK. So for whatever reason, `.Taxonomies` doesn't work. I commented that line out of my list and reloaded *hugo server* again. Now I got:

`(1 to 13 as before)
...
14. RSSLINK: 
15. TABLEOFCONTENTS: 
16. PREV: %!v(PANIC=runtime error: invalid memory address or nil pointer dereference)
17. NEXT: %!v(PANIC=runtime error: invalid memory address or nil pointer dereference)
18. PREVINSECTION: %!v(PANIC=runtime error: invalid memory address or nil pointer dereference)
19. NEXTINSECTION: %!v(PANIC=runtime error: invalid memory address or nil pointer dereference)
20. FUZZYWORDCOUNT: 100
21. WORDCOUNT: 81
22. READINGTIME: 1
23. WEIGHT: 0
24. ISNODE: false
25. ISPAGE: true`

So, why do some of the template page variables [as listed in the Documentation] work as expected, some fail to return anything, some return an inline [ie. on the HTML page] error and one returns a hugo error at compile time?

**Parting thought:**
The irony is that, when you do find out how to do something with Hugo, it's usually beautifully simple to implement. I've just added the new pagination to my site with a couple of lines of template code and a few CSS tweaks. Took me about ten minutes. Unfortunately it took me nearly half an hour trying to make sense of the documention to fathom out exactly how and where to add the new code and configure it. I don't think I'm particularly stupid but I find a lot of Hugo's documentation pretty baffling. 

Am I alone in this?

---
BTW: hugo version: Hugo Static Site Generator v0.13 BuildDate: 2015-02-22T04:02:30Z


  [1]: http://gohugo.io/templates/variables/
3 Likes

Agree that the doc could be better. It is written by tech nerds who like to code, the doc is often an afterthought. something we have to do …

I’m curious, you talk about “the new pagination” feauture, then talk about .Prev and .Next (a pager feature that has been there for a long time, nothing new).

See

And for an example, here is my pull request to add pagination to the gopheracademy blog’s front page:


It doesn’t get much simpler.

Yep. I know that .Prev and .Nex have been there a long time. I just hadn’t used them before, but decided to add those in, as well while I was implementing the new [as in 0,13] .Paginator function. That’s when I ran into the abovementioned confusion over variable scope, etc.

I did eventually find the documentation for the new pagination, you linked to above but it took me a while to guess where it would be [ie. under ‘Extras’]. I initially looked under

  • Getting Started > Configuration –assuming it would be included as one of the initial setup steps
  • Content –maybe it’s explained under organising content…?
  • Templates –maybe since pagination must have to be added into templates somehow…?

…before finally stumbling across it under ‘Extras’. Now I [subsequently!] realised that the github repo has links back to all these additional 0.13 features, but the point is there’s nothing on the http://gohugo.io site itself such as a “What’s New” page, or suchlike to help visitors find out about all this new stuff, without hunting through the docs –which aren’t searchable either.

I’m glad that you acknowledge the documentation is lacking in places. I don’t want my constructive criticism to be taken the wrong way. As I’ve said before, I love Hugo and [when you’ve sussed out what to do], it’s beautifully simple to use. I just think it’s a shame that all this elegant simplicity is sometimes hidden behind a thicket of often confusing documentation and inconsistent handling of simple user errors.

I believe you are making up some of the problems here.

I just went to the doc site, typed in “pagination” in the search box in the upper right corner of the main frame, and was taken directly to the correct page.

99.99% of all people know how to use a search provided by Google.

There’s a search box? News to me!

Yes, there SHOULD be. It was added some months ago. Could you try some cache-flushing-medicine? Like ctrl+R or similar. I believe it also requires JavaScript, so if you have that turned off, it could explain.

If you cannot get it to work, create an issue on GH with browser and OS info.

It’s not a caching issue, as I regularly have to force empty Firefox’s cache when doing CSS stuff and I’ve never seen a search box on the Hugo site. I’ve just checked in Chrome as well and no search box there either.

However, according to Safari…

Most peculiar!

It’s there on my Ubuntu box in both Firefox and Chrome. Weird. @anthonyfok added this, maybe he has some fix for it.

Mystery solved. I’ve got uBlock installed on Firefox and Chrome and it’s been blocking Google Analytics and [for some reason] Google CSE :

OK. Now we’ve solved that mystery, can we get back to arguing again?

2 Likes

A bit off-topic, but just for the record [and I stand to be corrected by anyone with greater knowledge than me of the Adblock filter syntax, which is also used by uBlock], the following works for me to whitelist the Google Search box on the Hugo Docs section, and other sites:

@@||google.com/cse/*

Stick it here:

Tada!..

Just wanted to say that yes, I share your confusion over variables. That said I’ve never met a project yet where variable scope doesn’t confuse me, its not unique to Hugo!

I share @stiobhart’s confusion about variables and what’s in context within
different templates.

I also agree with @adrinux that template variables and their context is
confusing in many different static site generators, not just Hugo.

I like the “hugo config” command which prints out the program’s
configuration. I wonder if something similar can be added to Hugo to empower
users to inspect variables within a rendering context? Something like “hugo
config”, but for template context. e.g. “hugo --dumpVars content/about.md”

Is this possible?

1 Like

Maybe, and it’s a good idea.

You would have to inspect it by reflection, but it should be doable.

I’ll create a GitHub issue for it.

There is of course this useful trick:

Thank you for the link to this tip. I found it via Google earlier, but now I have it bookmarked. To be honest, I wouldn’t have made it very far in porting my site without this useful tip.

It would still be nice to see a prettier version of this information, but I understand it’s not easy to do.

@jeff_ramnani, we’d certainly love your help making the docs experience
better though. You are in the perfect position of knowing what’s missing
and what could be better. Please help us make them be better. The docs are
in the Hugo repo http://github.com/spf13/hugo in the /docs folder and are
built by Hugo.

You are of course correct. Thankfully, I made some notes while I was still in a “beginner’s mind” while using Hugo.

I’ve opened some bugs and pull requests to address some of the things I stumbled on while I was getting started.


These two bugs address an issue I found where the Template -> Functions and Template -> Variables pages didn’t list all the functions and variables. I used those two pages a lot while I was writing my site’s templates. When something wasn’t there it broke my flow and made me think, “where was that again?”.

2 Likes

Sorry to bring this issue back up. I’m having the same issue as @stiobhart when it comes to listing taxonomies in a page. I’m using Hugo 0.14 and seeing the same error. Was there ever a fix for it?

Edit: Nevermind. I ended up using .Params.categories.