HUGO

Adding content for taxonomies

I am working on a site using v0.20.2 and I was wondering is it possible to assign content (in markdown) to individual taxonomies.

I would like to have a page that includes a description of a taxonomy term and then list all projects that matches with that term.

Here is a breakdown of what I have to try to do this.

config.toml contains the following for my taxonomies set up:

[taxonomies]
        language	= "Languages"
	framework	= "Frameworks"
	infrastructure	= "Infrastructure"
	tool		= "Tools"

archetypes/project.md looks like this:

---
title: 		""
description:	""
synopsis:	""
liveurl: 	""
date:	        ""
duration:	""
languages:	[]
frameworks: 	[]
infrastructure:	[]
tools:		[]
---

content/projects/opengl.md looks like this:

---
title: 		"OpenGL"
description:	"OpenGL experimentation on MacOS with C++."
synopsis:	"Learning C++ and OpenGL by coding up some demos which explore 3d mathematics, lighting and transformations."
date:		"2016-11-01"
duration:	"Ongoing"
languages:	
- C/C++
- GLSL
frameworks:
- OpenGL 3.2
tools:
- XCode
- CMake
- Github
---

This will be the content for this project.

layouts/_default/taxonomy.html looks like this:

<!DOCTYPE html>
<html lang="{{ .Site.LanguageCode }}">
    <head>
        {{ partial "head" . }}
    </head>
    <body>
        {{ partial "header" . }}
	<section class="taxonomy">
	    {{ .Content }} <- I want content here.
        </section>
	{{ partial "footer" . }}
   </body>
</html>

In the above file layouts/_default/taxonomy.html I want to be able to include a title, description and the content, but I don’t know where to put this, or even if GoHugo is able to do this.

I would like to know where need to put the .md file so I can have the {{ .Content }} tag render some content I have created.

I did see a mention of it in the documentation, but there was not enough information to go on to point me in the right direction.

Can anyone help?

Thanks

I know you can do section pages, using _index.md, so I would expect you can do the same with taxonomy list pages.
This page of the docs looks to be the best place to start - https://gohugo.io/content-management/organization/#index-pages-index-md

The _index.md works exactly like a normal content file, and as you desire can have content and frontmatter which you can call from your list.html.

Hi,

Thanks for the reply.

I tried something along the lines of that. From my understanding now, it seems that GoHugo picks up content from the url you have set up. In my shortcode for listing taxonomies I have the following:

{{ range $taxonomyname, $taxonomy := .Site.Taxonomies.Frameworks }}
    <li>
        <a href="{{ "/frameworks/" | relLangURL}}{{ $taxonomyname | urlize }}">
	    {{ $taxonomyname }}
	</a>
    </li>
{{ end }}

This would render a list of links to taxonomies with the links looking like http://example.com/frameworks/gohugo/

If I have something like content/frameworks/gohugo.md, then the content within that file will be rendered using the layouts/_default/single.html template by default. I think that’s what is happening.

I am wondering if there is a way I could get it to render content to the layouts/_default/taxonomy.html template instead.

I was able to achieve (somewhat) what I wanted to do. It’s still a work in progress so will edit this as needs must. Here is how I went about it.

Inside the layouts/_default/ directory I removed the two files terms.html and taxonomy.html. This would prevent hugo from rendering these templates when I clicked on one of my taxonomy terms.

I then added the following to the content/ directory:

  • frameworks/
  • tools/
  • languages/
  • infrastructure/

Note: These are the taxonomies I had specified inside my config.toml file as below:

[taxonomies]
	language	= "Languages"
	framework	= "Frameworks"
	infrastructure	= "Infrastructure"
	tool		= "Tools"

I then created the front matter content files inside each of those directories to map to the url for the content, so for example if I had the following file content/frameworks/coredata.html:

---
title: 		"Core Data"
description: 	"Data persitence framework for macOS and iOS applications."
proficiency:	"Beginner"
---

Core Data is the primary data persistence framework used for applications that run on Apple devices.

I would then be able to access it using the url http://example.com/frameworks/coredata/

To control which template renders this, I set up my templates as follows to match them to the names of the taxonomies.

  • layouts/frameworks/single.html

  • layouts/frameworks/list.html

  • layouts/tools/single.html

  • layouts/tools/list.html

  • layouts/infrastructure/single.html

  • layouts/infrastructure/list.html

  • layouts/languages/single.html

  • layouts/languages/list.html

With this, I can get content into my templates and control which templates are rendered.

I do get warnings about missing templates for the taxonomy terms but I am ignoring them for now because it seems to ‘work’ this way. I will keep an eye on that because future releases could come back to bite me.

Note: When I kept the files layouts/_default/terms.html and layouts/_default/taxonomy.html, Hugo would randomly choose between these templates and the ones mentioned above and load them at random - not good.

I have not read the entire thread, but you can create content files (i.e. _index.md) for every Node type of Page in the tree. I use the “old” Node term to distinguish them from regular pages.

Using them for all of your tag terms is maybe too much work, for low volume categories it works great.

The important parts here is that the location of the _index files must match the path to the taxonomy listing (or taxonomy term or whatever), and that these pages do not use the single.html template.

  • So /categories/_index.md = content page for the Categories terrms page
  • /categories/hugo/_index.md = content page for the Hugo category listing page

See the template documentation for which template(s) you need to render the taxonomy terms and list pages.

Hi Bep,

This is something that I had tried and couldn’t really get working.

Out of interest, is it possible for me to fetch all the content for a taxonomy term and list it?

My aim is to be able to create a shortcode that does this, so given a Languages term such as javascript, I could list all projects that have the javascript as one if its languages.

It would work something along the lines of:

{{% projects language="javascript" %}}

I am reading the documentation at https://gohugo.io/taxonomies/displaying/ and applying the code as follows:

<ul>
    {{ range .Site.Taxonomies.series.golang }}
        <li><a href="{{ .Page.RelPermalink }}">{{ .Page.Title }}</a></li>
    {{ end }}
</ul>

From my understanding, this should list all content that has been tagged with the series of golang.

For me, it doesn’t work. I have modified the example to match my set up as follows:

{{ range .Site.Taxonomies.Languages.c }}
    {{ .Page }} 
{{ end }}

What I would expect to see is some output in a list for all projects that have been assigned a language of c.

What is happening is that nothing is being rendered. I don’t see any warnings or errors pointing to this in particular.

I was surprised to find so little good taxonomy examples when I wrote this:

Hi Bep,

Thanks for the reply. I can start looking at that to see if I can get this working.

Here is what I have put together so far - this example listing all projects where the term occurs.

{{ $taxonomy 	:= .Params.taxonomy }}
{{ $term 	:= .Params.term }}
{{ $projects 	:= where .Site.Pages "Section" "projects" }}

<div class="categorised-projects">
    <h2>
	Projects that are using this
    </h2>

    {{ $taxonomy }} - {{ $term }}

    {{ range $projects }}
        {{ if in .Params.infrastructure $term }}
            <li>
	        {{ .Title }}
	    </li>
        {{ end }}
    {{ end }}
</div>

So this achieves the task of displaying a list of projects if the term I pass in matches. The only thing left to do is to try to set up the taxonomy too so it works in such a way I can search other taxonomies like languages, tools etc.

If you look at the line in the above code sample - {{ if in .Params.infrastructure $term }} ... {{ end }} I have infrastructure hardcoded. I would like to match that to the $taxonomy variable in the above code sample so I don’t have to repeat code.

Is it possible to do something like {{ if in .Params.$taxonomy }} ... {{ end }} ?

Thanks,

Matt

I would also note that you can also do lookups for taxonmy list and terms Pages via:

$categoriesTermsPages := .Site.GetPage "cagegories"
$hugoCagegoryPages :=  .Site.GetPage "cagegories" "hugo"

If I understand correctly, should the second those two list all pages that have a term hugo listed in the categories inside their front matter?

When I tried doing that in my shortcode, I got <nil> back as the result.

I have something working that will fetch all projects given a taxonomy and a term as follows.

I have created a shortcode called categorised_projects.html and placed it inside the layouts/shortcodes/ directory.

{{ $taxonomy 	:= .Params.taxonomy }}
{{ $term 		:= .Params.term }}
{{ $projects 	:= where .Site.Pages "Section" "projects" }}

{{ range $projects }}
    {{ if eq $taxonomy "framework" }}
	{{ if in .Params.frameworks $term }}
	    {{ .Render "card" }}
	{{ end }}
    {{ else if eq $taxonomy "infrastructure" }}
	{{ if in .Params.infrastructure $term }}
	    {{ .Render "card" }}
	{{ end }}
    {{ else if eq $taxonomy "languages" }}
	{{ if in .Params.languages $term }}
	    {{ .Render "card" }}
	{{ end }}
    {{ else if eq $taxonomy "tools" }}
	{{ if in .Params.tools $term }}
	    {{ .Render "card" }}
	{{ end }}
    {{ end }}
{{ end }}

This is a really ugly and hacky solution, but it works for now. The shortcode is called from one of my content files as follows:

{{% categorised_projects taxonomy="languages" term="Objective C" %}}

This will go through each project, see if it has the term Objective C inside its languages taxonomy and then render it if it does.

Sorry, I posted that “quick and from memory” and was wrong. The correct is:

$categoriesTermsPages := .Site.GetPage "taxonomyTerm" "cagegories"
$hugoCagegoryPages :=  .Site.GetPage "taxonomy" "cagegories" "hugo"

The magic first parameter is the Page.Kind, i.e. .Site.GetPage "home" wil get you the home page.

Hi Bep,

I gave those a try and they didn’t work as expected. I think they might fetch an actual page. What I was looking to do was fetch a list of pages that are projects that have the term HTML5 in their languages taxonomy.

I demoed the API, not spoon-feeding you your actual code.

(.Site.GetPage "taxonomy" "projects" "html5").Data.Pages

Might get you closer, but try to read and understand the documentation.

Hi Bep,

Thanks for all your help. I couldn’t get that to work so I will stick to my original (messy) solution and revisit it again. Once I figure out a cleaner way of doing it, I will post a Github gist and link it here for others to see it.

I am new to GoHugo and am also unfamiliar with the Go programming language, so I am sure I will crack it at a later date.

Matt