Possibility of rich taxonomies (as maps)

It would be nice if Hugo recognized taxonomy terms as maps, in addition to strings, in pages’ frontmatter. For example, taking a taxonomy named contributors, I could then use a frontmatter like:

# how it could be
contributors:
- name: Mary      # term string
  role: author
- name: John      # term string
  role: editor
- Paul            # term string, as today, to not break existing sites

Facing a taxonomy like that, Hugo could read only contributors.name (or another key, like term) to store the page terms. That way, one could specify not only the page terms, but the relation of page to each term. One could then use those “relation” values (like role) in templates, allowing a richer data model.

I think today this is not possible (please correct me if I’m wrong) without doubling those values:

# how it's today

# actual terms
contributors:
- Mary      # term string
- John      # term string
- Paul      # term string

# relation to terms
contributorRoles:
- name: Mary
  role: author
- name: John
  role: editor
- name: Paul

Is it possible or even feasible?

You can add metadata to your taxonomy: Taxonomy Templates | Hugo

So in your example,

<!-- content/contributors/mary/_index.md -->
title: Mary 
role: author

<!-- content/contributors/john/_index.md -->
title: John 
role: editor


<!-- content/contributors/Paul/_index.md -->
title: Paul


I’m aware of that possibility. It adds metadata belonging to the global (in entire site) taxonomy term. It works if, for instance, a contributor has always the same role across entire site.

But what I suggested here is different: keeping that same example, a way to specify a contributor’s role specific to a page. As such information is page-specific, it should be in that page’s metadata, not in a global content/contributors/<name>. It would, then, specify the relation between a specific page and a term.

Again, I know I can add such roles using metadata, Question is: doing so, today, I need to duplicate information (as explained in first post here).

Perhaps all of this wouldn’t make much sense in a blog-like website, where usually simple taxonomies as categories, tags or even authors (without any “role”) simply work.

A possible use case is a portfolio, where each page in a section represents a work. In this scenario, different roles for contributors make sense, for example.

Another example: in a music composer’s portfolio (my specific use case, btw), where each page represents a music, there would be a taxonomy like instruments. Following my suggestion, it’d be possible to specify number of performers for each instrument:

# in page's metadata, as other music would have other instrument quantities
# for a music for 3 violins, 2 cellos, 1 clarinet and 1 percussionist
instruments:
  - name: violin            # Hugo would read .name as term string
    quantity: 3             # and ignore other fields in taxonomy indexing
  - name: violoncello
    quantity: 2
  - name: clarinet
    quantity: 1
  - name: percussion
    quantity: 1

That way, a visitor could find this music via term pages (e.g. /instruments/violin), and site could implement quantity filters (JavaScript, not Hugo role), for example. (That same idea is applicable to contributors example).

(@pointyfar thank you, anyway.)

Seconding this. I need to classify my content by a skills framework, where each skill can be exhibited at a different level.

So, for example, I may end up with content front-matter that looks like this:

skills:
  - skill: CIISec/A - Information Security Governance and Management/A4 - Innovation & Business Improvement
    level: 4
  - skill: CIISec/A - Information Security Governance and Management/A5 - Behavioural Change
    level: 3

In my template, {{ if .GetTerms "skills" }} returns no results, and the block that is conditionally rendered based on that test is not rendered.

If I add a single normal skill to the front-matter, e.g.:

skills:
  - test
  - skill: CIISec/A - Information Security Governance and Management/A4 - Innovation & Business Improvement
    level: 4
  - skill: CIISec/A - Information Security Governance and Management/A5 - Behavioural Change
    level: 3

…then the test skill gets returned and the conditional block is rendered, but only with that term.

I’ve come up with a (very clumsy) workaround for this.

I define the taxonomy terms as normal, and then add a separate post front-matter param for the per-term values:

skills:
  - CIISec/A - Information Security Governance and Management/A4 - Innovation & Business Improvement
  - CIISec/A - Information Security Governance and Management/A5 - Behavioural Change
  - CIISec/C - Implementing Secure Systems/C3 - Secure Development
skills_ciisec_levels:
  - 4
  - 3
  - 4

Then, in my template:

  {{- if .GetTerms "skills" -}}
    <section>
      <h3>Skills</h3>
      <ul>
      {{- .Scratch.Set "i" 0 -}}
      {{- range ( .GetTerms "skills" ).ByTitle -}}
        {{- if hasPrefix .LinkTitle "CIISec/" -}}
          <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> <span class="level">{{ index $.Params.skills_ciisec_levels ( $.Scratch.Get "i" ) }}</span></li>
          {{- $.Scratch.Add "i" 1 -}}
        {{- else -}}
          <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
        {{- end -}}
      {{- end -}}
      </ul>
    </section>
  {{- end -}}

Obviously tweak to your needs; I can get away with the ByTitle sort because the skills I’m using have alphabetical IDs. I’m sure you could make something less hard-coded using index too, but this’ll do for my purposes for now.

In terms of actually implementing map taxonomies, I guess the main issue would be how to determine which field of a rich term definition is the actual term name (for generating its HTML page, place in the tree, etc). The easiest solution to me would seem to be having a defined param name (e.g. title or name) that would signify which field of a rich term should serve the role of the sole field on a normally-defined term.