DLM Tutorials

You can create a new site using

hugo new site hugo_tutorial

After that you can find a theme on the gohugo.io site

Front Matter

After creating a new piece of content using the command

hugo new hugo_tutorial

The default information at the of the file that’s created will look something like this:

---
title: "This is A's Title"
date: 2020-10-29T00:42:22-08:00
draft: true
---

This is called front matter.

You can modify the date and it will update the date displayed on the site, you can add an author and it will show in the single page view (but not in the list view) and you can change the title and it will update the link text on the list page and the title on the single page.

---
title: "This is A's Title"
date: 2020-10-29T00:42:22-08:00
draft: true
author: "Dakota"
---

Starting the server

If you want to see how your site looks in developement mode, you can run this command:

hugo server -D --watch --verbose

This will let you see posts that are still in draft mode. If you run

hugo server

you’ll see only posts where draft: false

Archetypes

There is a file called default.md in the archetypes folder that is used to make the default front matter that is created when you run hugo new my_new_file.md

---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

If you want to create an archetype that applies only to certain posts on the site, create a file with a name that matches a directory inside of the content folder.

For example, if we create an archetype called dir1.md then all files we create inside of /content/dir1 will use that archetype instead of the default:

---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
author: "Steve"
---

Shortcodes

Check out the video here. Video here

You can also read more about shortcodes here at gohugo.io

There’s a shortcode for a youtube video that looks like this:


Taxonomies

How we group content in a more efficient ways. Tags with keywords and Categories.

Tags go in the front matter

---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
tags: ["tag1", "tag2", "tag3"]
categories: ["cat1"]
moods: ["Happy", "Upbeat"]
---

Tags and Categories are built in taxonomies. We can also make our own like moods. But the issue is that it won’t be found because moods is not a default taxonomy. If we wnat this to work we need to specify the additional taxonomy.

Inside of config.toml we need to indicate that we have an additional taxonomy:

[taxonomies]
  tag = "tags"
  category = "categories"
  mood = "moods"

When we add additional taxonomies like mood, we need to add the taxonomies array to config.toml and also add tags and categories like above so they still work as well.

Templates

We have list pages and single pages.

All list style pages will use the layouts/_default/list.html template All single style pages will use the layouts/default/single.html template

Templates allow you to create an html skeleton that we can inject specific content into it.

<!-- list.html -->
<html>
<head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>Document</title>
</head>
<body>
    <!-- -->
     {{ partial "header" (dict "Kind" .Kind "Template" "List") }}
     <!-- takes whatever content you have and puts it into this part of the template-->
     {{.Content}}
     {{ range .Pages }}
          <div style="border: 1px solid black; margin:10px; padding:10px; ">
               <div style="font-size:20px;">
                    <a href="{{.URL}}">{{.Title}}</a>
               </div>
               <div style="color:grey; font-size:16px;">{{ dateFormat "Monday, Jan 2, 2006" .Date }}</div>
               <div style="color:grey; font-size:16px;">{{ if .Params.tags }}<strong>Tags:</strong> {{range .Params.tags}}<a href="{{ "/tags/" | relLangURL }}{{ . | urlize }}">{{ . }}</a> {{end}}{{end}}</div>
               <div style="color:grey; font-size:16px;">
                    {{ if .Params.categories }}   
                         <strong>Categories:</strong> 
                         {{range .Params.categories}}
                              <a href="{{ "/categories/" | relLangURL }}{{ . | urlize }}">{{ . }}
                         </a> {{end}}
                    {{end}}
               </div>
               <div style="color:grey; font-size:16px;">{{ if .Params.moods }}<strong>Moods:</strong> {{range .Params.moods}}<a href="{{ "/moods/" | relLangURL }}{{ . | urlize }}">{{ . }}</a> {{end}}{{end}}</div>

               <p style="font-size:18px;">{{.Summary}}</p>
          </div>
     {{ end }}
     {{ partial "footer" . }}
</body>
</html>

Here’s the single view

<!-- single.html-->
<html>
<head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>Document</title>
</head>
<body>
     {{ partial "header" (dict "Kind" .Kind "Template" "Single") }}
      <p>Test Text</p>
     <div style="margin:25px;">
          <h1>{{.Title}}</h1>
          <div style="color:grey; font-size:16px;">{{ dateFormat "Monday, Jan 2, 2006" .Date }}</div>
          <div style="color:grey; font-size:16px;">{{if .Params.author}}Author: {{.Params.Author}}{{end}}</div>
          <div style="font-size:18px;">{{.Content}}</div>
     </div>
     {{ partial "footer" . }}
</body>
</html>

If we add Test Text to the single template it will appear on all single pages.

List Templates

Check out hugo docs for List Templates for more info.

If we have an _index.md file in a directory without our content folder, that’s going to be a list page. In content/dir1/_index.md, this will use the template in themes/my_theme/layouts/_default/list.html

---
title: "Dir1"
date: 2020-12-07T14:23:36-08:00
draft: true
---

This is the home page

If we create a file in layouts/default/list.html this will override the one from our theme:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <!-- This will display the content-->
  {{.Content}}
  <!-- This allows you to iterate over the pages and access variables for each within the block. Read more about variables you can use in Page ranges on gohugo.io -->
  {{range .Pages}}
    <p><a href="{{.URL}}">{{.Title}}</a></p>
  {{end}}
</body>
</html>

Single Template

Variables

You can read about variables you can use in Page ranges on gohugo.io.

{{.Summary}}

a generated summary of the content for easily showing a snippet in a summary view. The breakpoint can be set manually by inserting

at the appropriate place in the content page, or the summary can be written independent of the page text. See Content Summaries for more details.

{{.Title}}

the title for this page.

{{.TableOfContents}}

the rendered table of contents for the page.

<!-- layouts/_default/single.md-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <main>
      <article>
      <header>
          <h1>{{ .Title }}</h1>
      </header>
          {{ .Content }}
      </article>
      <aside>
          {{ .TableOfContents }}
      </aside>
  </main>
  
</body>
</html>

{{.Type}}

the content type of the content (e.g., posts)

{{.WordCount}}

the number of words in the content

{{$.Param}}

{{ $.Param "header_image" }}

Home Page Templates

layouts/index.html This template will be used at the root route. It will only be used there and will not replace the list template.

Section Templates

Templates inside of layouts/_default are a default or kind of a fallback. So, if there’s a more specifically named template, it will take precedence over the default template.

When can I use separate templates?

If I create a new folder in the layouts directory that matches the name of a folder in the content directory, this will allow me to override templates that apply to that content directory.

The template lookup order can be referenced on the gohugo.io site.

Most common examples here would be the ability to use list and single templates that are specific to a particular type of content.

Master Template using baseof.html

If we create a file at layouts/_default/baseof.html, it will be used as the base template everywhere on our app. This baseof.html file is analagous to the application layout file in a rails app that you’ll generally find at /app/views/layouts/application.html.erb.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  Top of baseof
  <hr>
  {{ block "main" .}}

  {{ end }}
  <hr>
  {{ block "footer" . }}
    This is the default baseof Footer
  {{ end }}
  <hr>
  Bottom of baseof
</body>
</html>

In the /layouts/_default/single.com You can utilize the blocks and fill them in with content. If you don’t do anything the content of the baseof block will be displayed instead. This allows you to have a default footer for every page and then override it in a particular template if you so choose.

{{ define "main" }}
  <h1>This is the single template</h1>
  <main>
      <article>
      <header>
          <h1>{{ .Title }}</h1>
      </header>
          {{ .Content }}
      </article>
      <aside>
          {{ .TableOfContents }}
      </aside>
  </main>
{{ end }}

{{ define "footer" }}
This is the single page footer
{{ end }}

Hugo Variables

They are only accessible within list, single, or home templates. Read more about variables on gohugo.io

Variables about pages

{{ .Title }} => returns title of page in front matter
{{ .Date }} => returns date in the front matter
{{ .URL }} => returns the URL of the page

Say I define a variable in front matter

title: "This is the title of A"
date: date: 2020-10-29T00:42:22-08:00
draft: true
myVar: "my Value"

I’d access this using

{{ .Params.myVar}}

To create variables, I can do

{{ $myVarName := "aString" }}

I can access it by its name:

{{ $myVarName }}

I can use front matter variables for setting colors based on a partciular template.

title: "This is the title of A"
date: date: 2020-10-29T00:42:22-08:00
draft: true
color: "red"
<div style="background: {{ .Params.color }}"></div>

Functions

Functions are usable in template only.

{{ truncate 10 “This is a really long string” }}

will take the string and truncate it to 10 characters

{{ add 1 5}}

{{ sub }}

{{ singularize “dogs” }}

{{ range .Pages }}

In this case we are iterating through a collection of pages. We can access {{ .Title }}

{{ range .Pages }}
  {{ .Title }} {{ .URL }} {{ truncate 100 .Content }}
{{ end }}

Conditional Logic

{{ if }} eq lt le gt ge not

{{ $var1 := "dog" }}
{{ $var2 := "cat" }}

{{ if eq $var1 $var2 }}
  True
{{ else }}
  False
{{ end }}

Returns False

{{ $var1 := "dog" }}
{{ $var2 := "cat" }}

{{ if not (eq $var1 $var2) }}
  True
{{ else }}
  False
{{ end }}

returns True

{{ $var1 := 1 }}
{{ $var2 := 2 }}

{{ if lt $var1 $var2 }}
  True
{{ else }}
  False
{{ end }}

And operator

{{ $var1 := 1 }}
{{ $var2 := 2 }}
{{ $var3 := 3 }}

{{ if and (lt $var1 $var2) (lt $var1 $var3) }}
  True
{{ else }}
  False
{{ end }}
{{ $var1 := 2 }}
{{ $var2 := 2 }}
{{ $var3 := 3 }}

{{ if or (lt $var1 $var2) (lt $var1 $var3) }}
  True
{{ else }}
  False
{{ end }}
<h1>Simple Template</h1>
{{ $title := .Title }}

{{ range .Site.Pages }}
  <li>
    <a 
      href="{{.URL}}"
      style="{{ if eq .Title $title }} background-color: yellow; {{ end }}"
    >
      {{.Title}}
    </a>
  </li>
{{ end }}

Data Templates

This folder acts as a mini database for your application. You can use JSON, YML or TOML.

// data/states.json
{
  "AL": "Alabama",
  "AK": "Alaska",
  "AS": "American Samoa",
  "AZ": "Arizona",
  "AR": "Arkansas",
  "CA": "California",
  "CO": "Colorado",
  "CT": "Connecticut",
  "DE": "Delaware",
  "DC": "District Of Columbia",
  "FM": "Federated States Of Micronesia",
  "FL": "Florida",
  "GA": "Georgia",
  "GU": "Guam",
  "HI": "Hawaii",
  "ID": "Idaho",
  "IL": "Illinois",
  "IN": "Indiana",
  "IA": "Iowa",
  "KS": "Kansas",
  "KY": "Kentucky",
  "LA": "Louisiana",
  "ME": "Maine",
  "MH": "Marshall Islands",
  "MD": "Maryland",
  "MA": "Massachusetts",
  "MI": "Michigan",
  "MN": "Minnesota",
  "MS": "Mississippi",
  "MO": "Missouri",
  "MT": "Montana",
  "NE": "Nebraska",
  "NV": "Nevada",
  "NH": "New Hampshire",
  "NJ": "New Jersey",
  "NM": "New Mexico",
  "NY": "New York",
  "NC": "North Carolina",
  "ND": "North Dakota",
  "MP": "Northern Mariana Islands",
  "OH": "Ohio",
  "OK": "Oklahoma",
  "OR": "Oregon",
  "PW": "Palau",
  "PA": "Pennsylvania",
  "PR": "Puerto Rico",
  "RI": "Rhode Island",
  "SC": "South Carolina",
  "SD": "South Dakota",
  "TN": "Tennessee",
  "TX": "Texas",
  "UT": "Utah",
  "VT": "Vermont",
  "VI": "Virgin Islands",
  "VA": "Virginia",
  "WA": "Washington",
  "WV": "West Virginia",
  "WI": "Wisconsin",
  "WY": "Wyoming"
}
<!-- a single page template --> 
{{ range .Site.Data.states }}
  {{.}}
{{ end }}

This will print out all of the values inside of the JSON object.

// data/products.json
[{
  "_id": {
    "$oid": "5968dd23fc13ae04d9000001"
  },
  "product_name": "sildenafil citrate",
  "supplier": "Wisozk Inc",
  "quantity": 261,
  "unit_cost": "$10.47"
}, {
  "_id": {
    "$oid": "5968dd23fc13ae04d9000002"
  },
  "product_name": "Mountain Juniperus ashei",
  "supplier": "Keebler-Hilpert",
  "quantity": 292,
  "unit_cost": "$8.74"
}, {
  "_id": {
    "$oid": "5968dd23fc13ae04d9000003"
  },
  "product_name": "Dextromathorphan HBr",
  "supplier": "Schmitt-Weissnat",
  "quantity": 211,
  "unit_cost": "$20.53"
}]
<!-- single page template -->
{{ range .Site.Data.products }}
  <h2>{{ .product_name }}</h2>
  <p>distributed by {{ .supplier }}</p>
  <p>Quantity: {{ .quantity }}</p>
  <p>Price per unit: {{ .unit_cost }}</p>
{{ end }}

Partial Templates

Used to make simple modules for header/footer/navigation in a separte file that can be included in different templates.

Create a folder in layouts/partials All partial templates should be html

<!-- layouts/partials/header.html -->
<h1>{{.Title}}</h1>
<p>{{.Date}}</p>
<!-- layouts/_defaults/single.html -->
{{ partial "header" . }}

You can also use a dictionary:

{{ partial "header (dict "myTitle" "myCustomTitle "myDate" "myCustomDate")}}
<h1>{{ .myTitle }}</h1>
<p>{{ .myDate }}</p>

Custom Shortcodes

While partials are useful in templates, shortcodes can be used in the content directory.

<!-- layouts/shortcodes/myshortcode.html -->
This is my shortcode text.

In our content file:

{{< myshortcode >}}

Will display:

This is the shortcode text

We can also rework them to accept an argument

<!-- layouts/shortcodes/myshortcode.html -->
<p style="{{color: {{.Get `color`}}">>This is the shortcode text</p>

And then in our content file:

{{< myshortcode blue >}}

Will display:

This is the shortcode text

We can also use positional parameters instead of named parameters if we so choose:

<!-- layouts/shortcodes/myshortcode.html -->
<p style="{{color: {{.Get 0}}">>This is the shortcode text</p>

And then in our content file:

{{< myshortcode red >}}

Will display:

This is the shortcode text

If we want to use multiple lines for additional parameters, we can do that as well:

<!-- layouts/shortcodes/myshortcode.html -->
<p style="color: {{.Get `color`}}">This is the shortcode text</p>
<div>{{.Get `message` }}</div>

And then in our content file:

{{< myshortcode 
  color="green"
  message="an extra message"
>}}

Will display:

This is the shortcode text

an extra message

More complicated shortcodes

You can also have shortcodes that are not self closing:

<!-- layouts/shortcodes/wrappershortcode.html -->
<p style="color: {{.Get `color`}}">{{ .Inner }}</p>
<div>{{.Get `message` }}</div>

Then in content file:

{{< wrappershortcode color="orange" >}}
This stuff goes inside the .Inner function inside the shortcode
{{< /wrappershortcode >}}

Will display:

This stuff goes inside the .Inner function inside the shortcode

This will be very useful for creating reusable components with tailwindcss. One thing to note here, it’s not looking to render markdown. If you want to have markdown evaluated inside of the shortcode, you’d want to use a different wrapper for the shortcode:

https://discourse.gohugo.io/t/misunderstanding-of-shortcode-syntax-in-0-55/18538/25

<p style="color: orange"><h2 id="another-header-is-here">Another Header Is here</h2>
</p>
<div></div>
<p style="color: orange"><h2 id="hello-there">Hello there</h2>
</p>
<div></div>

Keep working in the woodshed until your skills catch up to your taste.
If you'd like to get in touch, reach out on LinkedIn.