Help:Categories
Create a blog category.
Blog categories are a way to group blog posts in a way, users are able to filter for. When a category was used that does not exist, a dummy category is shown on the categories page. Because of that, make sure to create a category for your blog post, if it doesn’t already exist.
Location
Directory | Description |
---|---|
content/<Language>/categories/ | The base directory of the blog categories |
Create a New Categories Page
To create a new page, use the command npm run create -- 'categories/<pageName>.md'
.
After that you can edit your newly created page, which is located in content/en/categories/<pageName>.md
.
Example
Create a new page foo
:
$ npm run create -- 'categories/foo.md'
>[email protected] create
> exec-bin node_modules/.bin/hugo/hugo new "categories/foo.md"
Content "/home/username/path_to_repository/repository_root_directory/content/en/categories/foo.md" created
Front Matter
Every Markdown file contains a header section, called front matter, in the YAML format to configure parts of the page or website. A categories page needs the following variables in the front matter.Variable | Type | Description |
---|---|---|
title | str | The title of the page or ressource |
description | str | The page description, normally for SEO |
lead | str | The page description shown after the title or in cards |
date | datetime | The datetime the page was created |
lastmod | datetime | The datetime the page was modified. Should be the same as date when the creating a new page |
contributors | list of
str | A list of contributors |
draft | bool | flase shows the page, true hides the page,
as it does not exist |
images | list of
str | Images, which will be converted and moved to the static directory. Remember to add every image you used here |
math | bool | This page contains LaTeX math. This option preloads the font and includes the KaTeX script in the script footer. |
The Datetime Type
The date and time according to ISO 8601 . The following table shows the extended format specified in ISO 8601 we use for our website to specify, when e.g. a page was created or edited. It has three parts:
- the date
- the time, including it's designator
T
- the timezone offset
Value | Optional | Description |
---|---|---|
2021 | No | Year |
07 | No | Month |
08 | No | Day of the month |
T | No | T is a designator, which indicates the start of the time representation |
12 | No | Hour |
34 | No | Minute |
56 | No | Second |
+ or - | Yes | + for a positive or - a negative timezone
offset |
01 | Yes | Timezone offset in hours |
02 | Yes | Timezone offset in minutes |
Formatting Examples
The following example uses the values from the table to show the format. It does not use the actual UTC. If you are not using the timezone offset, you must calculate UTC yourself.
- Example with timezone offset:
2021-07-08T12:34:56+01:02
- Example without timezone offset:
2021-07-08T12:34:56
Header Example
Remember, the front matter is aYAML
structure embedded into the
Markdown file. The ---
delimiters signal Hugo that this is a front
matter in the YAML
format. Here is a generated example, how the
front matter might look like:
---
title: "MyTitle"
description: "A description of the page content"
lead: "A lead to the page content"
date: 2021-10-08T14:48:42+01:00
lastmod: 2021-10-08T14:48:42+01:00
contributors: ["UserA" "UserB" "UserC"]
draft: false
images: ["avatar.svg" "foo.svg" "bar.svg"]
math: true# This is an example for a comment in YAML
---
Code
Below you find the implementation of the layout.
HTML
Term Page Layout
Defined in layouts/categories/term.html
.
{{/*<!--
Categories Layout
=================
Contributors: Michael Sasser
Maintainer: Michael Sasser
License: MIT
Version: 1
Type: Term
LAYOUT: /layouts/categories/term.html
DOCS: /content/<language>/wiki/Help:Layout_Categories.md
Description
-----------
The term layout page for the blog categories.
Changelog
=========
Version 1
---------
Initial release
-->*/}}
{{ define "main" }}
{{ $blog := where .Site.RegularPages "Section" "blog" }}
{{ $pages := slice }}
<!-- Find the category page -->
{{ $category_page := "" }}
{{ range (where $.Site.RegularPages "Section" "categories") }}
{{ if eq (lower .Title) (lower $.Title) }}
{{ $category_page = . }}
{{ end }}
{{ end }}
<!-- Find the blog posts (pages) -->
{{ range $temp_page := (where $blog "Params.categories" "!=" nil) }}
{{ range $c := .Page.Params.categories }}
{{ if eq (lower $c) (lower $.Title) }}
{{ $pages = $pages | append $temp_page }}
{{ end }}
{{ end }}
{{ end }}
<div class="container">
<div class="section pt-5">
<a href="/categories/">← Back to categories</a>
<div class="row g-5 justify-content-center">
<div class="col-md-12 col-lg-9 col-xl-9">
<h1 class="pb-2 mb-2 fst-italic">
<i class="fa fa-folder-open"></i>
Category:
{{ .Title | title }}
</h1>
<p class="lead">
{{ with $category_page }}
{{ .Params.lead | safeHTML }}
{{ end }}
</p>
<div class="pb-4 mb-4">
{{ with $category_page }}
{{ .Content }}
{{ end }}
</div>
{{ $paginator := .Paginate $pages -}}
{{ range $paginator.Pages -}}
{{ partial "main/blog-post-list-layout.html" . -}}
{{ end }}
<div class="pagination justify-content-center">
{{ $.Scratch.Set "paginator" true }}
{{ template "_internal/pagination.html" . }}
</div>
</div>
{{ partial "main/blog-sidebar.html" . }}
</div>
</div>
</div>
{{ end }}
Terms Page Layout
Defined in layouts/categories/terms.html
.
{{/*<!--
Categories Layout
=================
Contributors: Michael Sasser
Maintainer: Michael Sasser
License: MIT
Version: 1
Type: Terms
LAYOUT: /layouts/categories/terms.html
DOCS: /content/<language>/wiki/Help:Layout_Categories.md
Description
-----------
The terms layout page for the blog categories.
Changelog
=========
Version 1
---------
Initial release
-->*/}}
{{ define "main" }}
<!-- Check if path for pagination should be /blog/ or /blog/<year>/ -->
{{ $blog := (where .Site.RegularPages "Section" "blog") }}
<!-- Store for all elements (not uniq) -->
{{ $categories := newScratch }}
{{ $temp_categories := slice }}
<!-- find all categories and number of occurences -->
<!-- The structure is so, because sort removes the key -->
<!-- structure: [{<category name>: {"category" : <category name>, "count": 1, "pages":[page_1, page_n]}}, ...] -->
{{ range $temp_page := (where $blog "Params.categories" "!=" nil) }}
{{ range $c := .Page.Params.categories }}
<!-- was there already an occurence of that category -->
{{ if in $temp_categories (lower $c) }}
<!-- get current value of count -->
{{ $count := ($categories.Get (lower $c)).count }}
{{ $pages := ($categories.Get (lower $c)).pages }}
{{ $category_page := ($categories.Get (lower $c)).category_page }}
<!-- Write a new map back, with the current count + 1 and the additional page -->
{{ $categories.Set (lower $c) (dict "category" (lower $c) "count" (add $count 1) "pages" ($pages | append $temp_page) "category_page" $category_page) }}
{{ else }}
<!-- get category page, by compareing the category page with the category name used in the blog post (the one from above) -->
{{ $category_page := "" }}
{{ range (where $.Site.RegularPages "Section" "categories") }}
{{ if eq (lower .Title) (lower $c) }}
{{ $category_page = . }}
{{ end }}
{{ end }}
<!-- create the category with the initial count of 1 -->
{{ $categories.Set (lower $c) (dict "category" (lower $c) "count" 1 "pages" (slice $temp_page) "category_page" $category_page)}}
{{ $temp_categories = $temp_categories | append (lower $c) }}
{{ end }}
{{ end }}
{{ end }}
<!-- {{/* values: {{sort $categories.Values "count" "desc"}}<br /> */}} -->
<div class="container">
<div class="section pt-5">
<a href="/blog/">← Back to blog</a>
<div class="row g-5 justify-content-center">
<div class="col-md-12 col-lg-9 col-xl-9">
<h1 class="pb-2 mb-2 fst-italic">
<i class="fa fa-folder-open"></i>
{{ .Title }}
</h1>
<p class="lead">{{ .Params.lead | safeHTML }}</p>
<div class="text-center pb-4 mb-4">{{ .Content }}</div>
<div class="row row-cols-1 row-cols-md-3 g-4">
{{ range (sort $categories.Values "count" "desc")}}
{{/* {{.}}<br /> */}}
<div class="col">
<div class="card text-center h-100">
<div class="card-image">
<a href="{{ .Page.Permalink }}">
<!-- The first page hugo finds (any page) -->
{{ $firstChild := index .pages 0 }}
<!-- If the category_page exists -->
{{ if ne .category_page "" }}
<!-- This overwrites any existing image to the first one -->
<!-- in the category -->
{{ $firstChild = index .category_page }}
{{ end }}
<!-- does images exist? -->
{{ if isset $firstChild.Params "images" }}
<!-- if it has more then one elements -->
{{ if gt (len $firstChild.Params.images) 0 }}
{{ $images := $firstChild.Params.images }}
<!-- image_name e.g. "my.svg" -->
{{ $image_name := (index $images 0) }}
<!-- image_path e.g. "/path/to/" -->
{{ $image_path := $firstChild.RelPermalink | relURL }}
<!-- avatar e.g. "/path/to/foo.svg" -->
{{ $image := $image_name | printf "%s%s" $image_path | printf "%s" }}
<img
src="{{ $image }}"
class="card-img-top lazyload blur-up"
alt=""
width="100%"
height="256px"
/>
<!-- Not able to find an image -->
{{ else }}
<svg
class="card-img-top bd-placeholder-img lazyload blur-up"
width="100%"
height="256px"
xmlns="http://www.w3.org/2000/svg"
role="img"
aria-label="Placeholder: Thumbnail"
preserveAspectRatio="xMidYMid slice"
focusable="false"
>
<title>Missing Thumbnail</title>
<rect
width="100%"
height="100%"
fill="#2f3237"
></rect>
<text x="50%" y="43%" fill="#dee2e6" dominant-baseline="middle" text-anchor="middle" dy=".3em" style="font: italic 20px sans-serif;">
Missing
</text>
<text x="50%" y="57%" fill="#dee2e6" dominant-baseline="middle" text-anchor="middle" dy=".3em" style="font: italic 20px sans-serif;">
Thumbnail
</text>
</svg>
{{ end }}
{{ end }}
</a>
</div>
<div class="card-body pb-1">
<a class="stretched-link" href="/categories/{{.category}}"></a>
<h4 class="card-title">{{ .category | title }}</h4>
<p class="card-text">
{{ if ne .category_page "" }}
{{ .category_page.Params.lead }}
{{ else }}
<span class="text-muted">This category is new and has no description, yet.</span>
{{end}}
</p>
<div class="card-footer">
<small class="text-muted">
{{ .count }}
Post{{ if ne .count 1 }}s{{ end }}
</small>
</div>
</div>
</div>
</div>
{{ end }}
</div>
</div>
{{ partial "main/blog-sidebar.html" . }}
</div>
</div>
</div>
</div>
{{ end }}
Archetype
Defined in layouts/categories.md
.
---
title: "{{ replace .Name "-" " " | title }}"
description: ""
lead: ""
date: {{ .Date }}
lastmod: {{ .Date }}
contributors: []
draft: true
images: ["{{ .Name | urlize }}.jpg"]
---
Categories | Contributors |
---|---|
Help, Contribute and Layout | Michael Sasser |