HUGO

Having trouble with taxonomies

I want to access a metadata value associated with a given author.

I have:

content
    author
        mark
            _index.md

_index.md is:

+++
title = "Mark Richards"
author_image = "/images/mark-author.jpg"
+++

On a page that lists post-cards for each page in a section (so the context will be a content post–or simply a page) I want to include a teeny little photo of the author of the page that is the anchor for a link to all of that author’s posts. I already have working the code that grabs the name of the author of the post-card. With that I should be able to get the link to his/her/their picture. But, I am stumped how to do it.

The name of the author (not the title–so it is “mark” in this case, not “Mark Richards”) is:

.context.Param "author"   # result is "mark"

The link to all of mark’s posts is:

{{$url := path.Join "/author/" (.context.Param "author") | urlize }}  # result is /author/mark

What I now want is $img, which should be “/images/mark-author.jpg”. But, I don’t want to build it up using literals like I did before. I should be able to read it from the front matter for mark in the appropriate _index.md.

Seems like there should be a direct way using one of the taxonomy functions especially since I know the taxonomy is “author” and I have “mark”. Right now I just hardcoded the src= link in the img tag to get everything else working.

Which function? Which arguments?

By the way, this is the casper3 theme. No activity and replies on issues in that repo. The layout for the postcard uses a hard-coded link to a bogus site and a hardcoded svg drawing as the picture. So, no help there.

put the images in the asset dir ( ./assets/images/mark-author.jpg)

{{ $image := resources.Get .Params.author_image }}
<img  src={{ $image.RelPermalink }} width={{$image.Width}} height={{$image.Height}} 
 alt="{{ .Params.Title }}" />

Hope this helps

Thanks, that helps a lot. I would have never figured that out because I wasn’t able to put together the pieces from the fragmentary way the reference docs work.

All images are in static/images. Could the same thing work from this directory?

Easy enough to move a few images (there are very few author id pics). But if I move all it will be a bear because there are hundreds and many, many posts will need to have image links updated. Any problem if some images are in ./static/images and others in ./assets/images? Guess I’ll find out. Will report back.

Thanks again.

YIKES! That blew up hard. It doesn’t like resources.get. Seems like I am back at square 1.

The error message mess below refers to lines 33:34 of post-card.html layout. These are lines 33:34:

            {{ $image := resources.Get .Params.author_image  }}

Here is where variable $image is used:

                        <li class="author-list-item">
                            <div class="author-name-tooltip">{{.context.Param "author"}}</div>
                            <a href= {{$url}} class="static-avatar author-profile-image"><img src={{ $image.RelPermalink }}  alt="{{ .Params.Title }}"  width="40" height="40"></a>
                        </li>

I also tried replacing .Params.author_image with `(.context.Param “author_image”)’ but this blew up spectacularly also.

Note that I moved the author jpgs to ./assets/images/. But, that meant I split my images across ./static/images for content images in posts and the suggestion just for the author images. Not clear this caused the problem.

One of the challenges of Hugo is that it is very difficult to create focused miniature test cases or to see static results. The code occurs in the context of all of the web resources and the entire theme. Hard to do a print() debugging of a big ball.

I did throw in an arbitrary

somewhere I thought it would actually appear:

                        <li>
                            <p> {{ .Params.author_image }}  </p>
                        </li>

There was no output. I don’t think this use retrieves anything: it can’t. .Params. refers to the context of the content being rendered–which is content from a page. Page front matter doesn’t contain a variable author_image. This variable only exists within the author taxonomy metadata as in my original post. That’s what makes this hard: how do you reach into that author taxonomy metadata for a specific author.

Hugo’s just hard if you reach behind the velvet ropes. Stay behind the velvet ropes and it’s amazing.

error message:

lewis@MacBook-Pro-2 a-view-hugo % hugo server -d ~/output
Start building sites …
ERROR 2021/02/19 12:50:16 render of "page" failed: execute of template failed: template: _default/single.html:69:4: executing "main" at <partial "post-navigation.html" .>: error calling partial: execute of template failed: template: partials/post-navigation.html:9:20: executing "partials/post-navigation.html" at <partial "post-card.html" (dict "context" . "index" 1)>: error calling partial: "/Users/lewis/git-repos/a-view-hugo/themes/hugo-casper3/layouts/partials/post-card.html:33:34": execute of template failed: template: partials/post-card.html:33:34: executing "partials/post-card.html" at <resources.Get>: error calling Get: dirs not supported resource types: &{0xc000f52010 map[baseDir:/Users/lewis/git-repos/a-view-hugo filename:assets isOrdered:false lang: module:project mountRoot: mountWeight:2 opener:0x458c220 sourceRoot:/Users/lewis/git-repos/a-view-hugo/assets watch:true]}
ERROR 2021/02/19 12:50:16 render of "page" failed: execute of template failed: template: _default/single.html:69:4: executing "main" at <partial "post-navigation.html" .>: error calling partial: execute of template failed: template: partials/post-navigation.html:9:20: executing "partials/post-navigation.html" at <partial "post-card.html" (dict "context" . "index" 1)>: error calling partial: "/Users/lewis/git-repos/a-view-hugo/themes/hugo-casper3/layouts/partials/post-card.html:33:34": execute of template failed: template: partials/post-card.html:33:34: executing "partials/post-card.html" at <resources.Get>: error calling Get: dirs not supported resource types: &{0xc00067c010 map[baseDir:/Users/lewis/git-repos/a-view-hugo filename:assets isOrdered:false lang: module:project mountRoot: mountWeight:2 opener:0x458c220 sourceRoot:/Users/lewis/git-repos/a-view-hugo/assets watch:true]}
ERROR 2021/02/19 12:50:16 render of "page" failed: execute of template failed: template: _default/single.html:69:4: executing "main" at <partial "post-navigation.html" .>: error calling partial: execute of template failed: template: partials/post-navigation.html:9:20: executing "partials/post-navigation.html" at <partial "post-card.html" (dict "context" . "index" 1)>: error calling partial: "/Users/lewis/git-repos/a-view-hugo/themes/hugo-casper3/layouts/partials/post-card.html:33:34": execute of template failed: template: partials/post-card.html:33:34: executing "partials/post-card.html" at <resources.Get>: error calling Get: dirs not supported resource types: &{0xc0011c0010 map[baseDir:/Users/lewis/git-repos/a-view-hugo filename:assets isOrdered:false lang: module:project mountRoot: mountWeight:2 opener:0x458c220 sourceRoot:/Users/lewis/git-repos/a-view-hugo/assets watch:true]}
ERROR 2021/02/19 12:50:16 render of "page" failed: execute of template failed: template: _default/single.html:69:4: executing "main" at <partial "post-navigation.html" .>: error calling partial: execute of template failed: template: partials/post-navigation.html:9:20: executing "partials/post-navigation.html" at <partial "post-card.html" (dict "context" . "index" 1)>: error calling partial: "/Users/lewis/git-repos/a-view-hugo/themes/hugo-casper3/layouts/partials/post-card.html:33:34": execute of template failed: template: partials/post-card.html:33:34: executing "partials/post-card.html" at <resources.Get>: error calling Get: dirs not supported resource types: &{0xc00105e010 map[baseDir:/Users/lewis/git-repos/a-view-hugo filename:assets isOrdered:false lang: module:project mountRoot: mountWeight:2 opener:0x458c220 sourceRoot:/Users/lewis/git-repos/a-view-hugo/assets watch:true]}
Built in 1234 ms
Error: Error building site: failed to render pages: render of "page" failed: execute of template failed: template: _default/single.html:69:4: executing "main" at <partial "post-navigation.html" .>: error calling partial: execute of template failed: template: partials/post-navigation.html:9:20: executing "partials/post-navigation.html" at <partial "post-card.html" (dict "context" . "index" 1)>: error calling partial: "/Users/lewis/git-repos/a-view-hugo/themes/hugo-casper3/layouts/partials/post-card.html:33:34": execute of template failed: template: partials/post-card.html:33:34: executing "partials/post-card.html" at <resources.Get>: error calling Get: dirs not supported resource types: &{0xc000d0a6f0 map[baseDir:/Users/lewis/git-repos/a-view-hugo filename:assets isOrdered:false lang: module:project mountRoot: mountWeight:2 opener:0x458c220 sourceRoot:/Users/lewis/git-repos/a-view-hugo/assets watch:true]}

Further–and simpler:

The assets folder is not generated in the site output. Hugo only generates it if any of its contents are actually referenced. So, the coding proposed doesn’t actually reach in there so Hugo doesn’t bother creating ./assets/images in the output.

BTW splitting the images causes no harm. The top level images folder used by pages is generated and all images appear where they should be.

static directory is copied without change … and NOT used for resources
create directory assets in the project directory, same level as content directory
where .context comes from??? not needed

can you give us a repository for help? Guessing does not wok.

Here is another interesting observation.

In the pre-gen file structure we have both:
./static/images/ → a bunch of subdirectories and a few image files at this level
./assets/images/ → only the author images at this level

In the post-gen output (static pages of the finished website) the image directories above are combined into one!
./images/ everything from the above two folders

and when I look at the running site with developer tools, the explicit paths to the author images (which must be accessed on the target page referring to a link that actually exists in the output website–where else?) it points to ./images. So, Hugo simply combines static/images and asset/images.

and there are no metadata pages anywhere. Either the metadata got used to generate something in the output or it didn’t and it simply goes away if not used. It gets used to generate taxonomy pages of various kinds: author, category–whatever we ask for. Section is a different kind of taxonomy: the sections become top level directories of the web site.

In the taxonomy output pages, the links to images have been resolved to where the images are put in the output. it’s the only place the images can be accessed when a page is rendered by a browser. For sections, these images go into the section list page header.
For the author taxonomy, there is no header image (I could do it with an author metadata page–but no need). But in the author post cards I want to have an image of the author.

There are two ways that could happen. I can’t go get it from a page, which is why .Site.GetPate must fail–because this can only reach output generated pages. Instead, I have to predict where the image might be used in the finished site and read it from there-- but the fields of taxonomy front matter don’t exist in the output website. So, I need to “predict” where the picture is used and construct a URL to that place. Would work but it’s sort of wrong.

The other way is to have Hugo access the picture at site generation time when Hugo has access to the pre-gen directory structure. Of course, this is how Hugo does everything. So, that means there is a way to refer to the taxonomy per item metadata. Hugo uses this for “standard” taxonomies like category, author, etc–things that can be extracted from page front matter. So, Hugo uses this to build the taxonomy list pages. We don’t know how Hugo does this and where it finds the necessary information because that’s in the Hugo code. Once Hugo has read that information it’s in some in-memory data structure until Hugo is done with the data.

What we need to do to use the taxonomy metadata in a another way is know how to reference it. It’s possible because Hugo does it for other purposes.

Where oh where in the API is the right function?

No, it doesn’t work although the problem has NOTHING to do with the image directories. Clearly Hugo finds the needed images to create the author “sections” (or taxonomy pages) which include post cards of posts written by each author. This works as before. The key has to do with my subsequent post. We need an API to get to the same information that Hugo uses to generate “finished” taxonomy pages.

repo: https://github.com/lewisl/a-view-hugo

I did this terrible hack and it works, but it IS a terrible hack. I would like to get this right, but now I can wait until the light bulb goes off.

            {{ $author := .context.Param "author"}}
            {{ $url := path.Join "/author/" $author | urlize }}
            {{ $image := path.Join "/images/" (print $author ".jpg") | urlize}}

The following didn’t work because .Site.Taxonomies.author appears to be broken (for me):

            {{  $authors := .Site.Taxonomies.author }}
            {{ $authormap := index $authors $author }}
            {{ $image := index (index .Site.Params.author ($author)) "author_image" }}
            {{ $title :=  index (index .Site.Params.author ($author) ) "title"  }}
            {{ $title := $authormap.title }}

These are just experiments, but because .Site.Taxonomies.author fails they all fail.

Context is needed because the front matter attributes don’t come from the author, but from individual posts of the author.

Sent post with repo in it.

Not quite clear on your terminology but I put the images back in static and got rid of asset, for which there was no need.

.Site.Taxonomies.author returns nil even though I have 2 authors. So, I can’t use any of the advice based on this map actually existing.

Does it matter that I don’t have explicit Taxonomy or Data of authors?

Instead, author hames are used in front matter of posts.

And, I have this:

./content
      /author
            /mark
                  _index.md
            /jane
                  _index.md

This seems to be the new wave way to do this and legitimate. I have a successful author list page that lists all authors and provides lists of all of their posts: all created automatically.

I should also point out that I have this in config.toml, which confirms that author is author not authors:

[taxonomies]
  tag = "tags"
  category = "categories"
  author = "author"

But, .Site.Taxonomies.author is nil. Sometimes it seems $.Site.Taxonomies.author is appropriate. Sure, documentation says why but in practice it’s hard to know why, which, when.

And I use “author” not “authors” though I’ve tried .Site.Taxonomies.authors.

I guess I am getting exhausted by all of the fragility and inconsistencies and opaque documentation of Hugo.

Hi there,

Please have a read about Requesting Help . Please provide a link to where you have your site code, because it is difficult to help you without being able to replicate your issue. .Site.Taxonomies.author should work, if the taxonomies are configured correctly, but we don’t know what else is going on in your site code, and we cannot guess just based on your description.

There are other posts about then issue.

In any case: GitHub - lewisl/a-view-hugo

The challenge is in the partial: post-cards.html.

the post card is for the current section or author. the footer of the post-card should show a tiny photo of the post author.

The author photo is in the front matter of _index.md for that author in a hierarchy in the content dir:

./content
     /author
           /mark
                 _index.md

_index_md contains:

+++
title = "Mark Richards"
author_image = "/images/mark.jpg"
+++

Rather than relying on knowing the image naming scheme and where the author photos are placed, we should simply look them up from the author metadata.

config.toml contains:

[taxonomies]
tag = “tags”
category = “categories”
author = “author”


The solution seems to require getting the author value of .Site.Taxonomies.author and the "author_image" key from the map for a specific author.  All relies on .Site.Taxonomies.author actually working.

I've spent hours on this, reading documentation and trying things, receiving some suggestions that went down the wrong track. Reading taxonomy maps is heading down the right path...

Thanks.

I’ve merged both of your topics into one because it’s essentially the same question.

You need to understand the concept of context: Introduction to Hugo Templating | Hugo

1. No author images on homepage

When you are on your homepage, using /layouts/index.html, you have this bit:

{{ range $index, $element := .Pages }}
    {{- partial "post-card.html" (dict "context" . "index" $index "home" $.IsHome) -}}
{{ end }}

It iterates through your .Pages. Then for each .Page it renders the post-card partial. Now, look at what information you are passing through to the partial. You are passing context, which is the current .Page in the iteration.

Now look at the post-card partial. If you print the “dot”, {{ . }} you will see that it does indeed get the info you passed to it.

Let’s take one example.

On your homepage, the first post I see is “New England Streams”. If you print the dot inside the partial, this is what you will see:

map[context:Page(/new_england_streams/_index.md) home:true index:0]

context contains the page new_england_strams/_index.md. If you look at this page, this is all the frontmatter it has:

+++
title = "Amsterdam Expats"
cover_image = "/images/2018/06/cropped-singel-houses-crop.jpg"
description = "Two months of delightful living"
+++

It has no author information.

So when the partial looks at {{ $author := .context.Param "author"}}, this is nil.

.Site.Taxonomies.author is nil

Again, we look at the post-card partial, specifically the value of the dot :

map[context:Page(/new_england_streams/_index.md) home:true index:0]

Recall from the doc:

  • In the top level of your template, this will be the data set made available to it.

The dataset available to the partial is the argument that you passed into it:

(dict "context" . "index" $index "home" $.IsHome)

so when you are in the partial, if you call .context you will get the current page in the iteration, when you cal .index you get the $index of the iteration, etc.

Now what do you get when you call {{ .Site }}?

Nothing. Because this was not passed into your partial.

Which means .Site.Taxonomies will be nil, and .Site.Taxonomies.author will be nil.

current state

to summarise the current state:

  1. your page does not have author information
  2. your partial does not have access to the .Site variable.

how to resolve

  1. add author information to your page.

  2. instead of .Site, you can use site: Site Variables | Hugo

Thanks. That helps a lot.

Should I have different layouts for site (a list of the 5 sections), a section (many posts), author (a list of 2 authors), an author page (many posts). Or I could have a conditional within the template.

The existing list.html works for anything that receives many posts (single author, section). List.html is also used for the pages with only section members (index, and single author page).

I already modified index.html to handle the list of sections. You are correct that sections don’t have authors. I could just create a pseudo author such as that just repeats the section name. The link is already fine: goes to a list of all the section posts as post-cards.

I am thinking that what I am trying to do only makes sense for pages that list multiple posts.

For the other “levels” I could edit the front matter and make a minor tweak to the templates.

Thanks for taking the time to point out the obvious.

If your only issue is the author info, you could just check if an author is defined:

{{ if $author }}
<footer class="post-card-meta">
   ...
</footer>
{{ end }}

{{ if $author }}

{{end}}

Works. for lists generated of the sections, each with a post-card, there is no author. for lists generated of the authors, there is no author of the items in the author taxonomy. For lists that contain posts, there will be author.

But, I am far from satisfied. Or I remain quite flustered. I need to get the author image. The only way I can do it is because I know the name of the images directory and I know the file name. So, I can catenate a path to the file. This is obviously wrong. A given author’s image might have a differently constructed file name.

The correct way to do this is to access the the author_image variable from the author’s front matter in _index.md:

+++
title = "Mark Richards"
author_image = "mark-said-foobar.png"
+++

This file name deliberately violates a sensible naming scheme and, oh, it’s a png not a jpg. So, the only way to get a handle to this image is to read the author taxonomy member’s front matter.

I can see no way to do so and I can find nothing in any posts in discourse for doing so. What people do is they get the reference to a taxonomy page (for a single member of that taxonomy) and then they get the front matter of that page. That doesn’t work: I want the variable.

Clearly, Hugo itself totally has access to this. When it nicely generates the taxonomy page for author (listing all authors) it uses the image of each author. So, Hugo finds where each image is. When it generates the list page for a single author, which lists that author’s posts, the banner image is the correct image. So, Hugo has the path to these images in some data structure, probably a map or dict (whatever Go calls mapping data structures).

I want that data structure. I do NOT want to scape the metadata of a generated page because the needed value is NOT going to be there.

There has to be a way to do this. I can get (index .Site.Taxonomies.author "mark"). (See, I am not completely incapable of reading the documentation…) But, this is an array of page references for the posts that Mark has written. It is not a map that has Mark’s pages and Mark’s metadata. It should be clear enough that I want to get Mark’s metadata. Specifically index (index .Site.Taxonomies.author "mark") "author_image" does not work. It’s not in there because the returned data structure is a slice/array of type page.WeightedPages.

So, how can this be done?

ju52 has a post in which get page returns the desired page (implicit–he doesn’t show that), but once the right page is obtained, he scrapes the page to get an image as follows:

$pic := $.Page.Resources.GetMatch (.Get "src")
<img src = {{ $pic.PermaLink }}

Having left out some specifics, this is page scraping and it should work. Is this really the only way?

You can predefine author information in content …

Check the generated author directories under public/author and create this directories under /content/author.

There you can create _index.html for every autor. create ./images per author and put the picture in it.

Easy - use always the same picture name or use resource functions to find an image

{{ range first 1 (.Resources.ByType "image") }}

gives you the alphabetical first picture. ( I used it in my feed templates, link below. )

copy the needed template to layout/author
there are 2 templates

terms.html.html can list all authors
list.html.html can all pages for a single author

check out my sample, you see this templates for “series” and “tags”.

I don’t know, how to put it in the home page now, it’s late for me today.
hope this helps

OK. I do put the information per author in /content/author/george/_author.md already.

I can put the images there: it’s just like a page bundle for a post except this time it’s a page bundle for an item in a taxonomy.

Your approach relies on the right physical order of images rather than naming of the image.

At this point I don’t rely on a layout for the author taxonomy because the author photos are grabbed to appear as part of a post-card partial wherever posts are listed (posts have authors–items higher in the hierarchy don’t). Also used on the author taxonomy but the standard list template works with the slight modification mentioned above.

I will take a look at your sample because it illuminates some new aspects of Hugo–namely Resources variable and what can be accessed. That’s cool.

By your answer I can tell that the metadata entered in various files of the site input/design are not directly accessible. That seems fundamental to the way Hugo works. I might propose opening up access to metadata but for now I have 2 different ways to “skin this cat” (no offense to cats or cat lovers…).

Thanks for sticking with me on my cantankerous exploration.

  • Lewis

Sorry. I didn’t see anything like what you are describing in the terms.html.html or list.html.html layouts under series or tags.

And by the way the front matter I actually use is thus:

+++
title = "Mark Richards"
author_image = "/images/author_image.jpg"
+++

I'll give yours a try.  It's a might bit less of a hack than mine as it is not sensitive to the file name.