Creating/coding for the web is not my primarily focus but i think it is an important skill to have and will be increasingly so. As part of a 1 year program in business and marketing I did almost 20 years ago we had a short course in web development. The instructor insisted that we should use Dreamweaver (Macromedia at the time). I did not like it, I thought it hid the internal mechanics and I wanted to get closer to the actual language so I ended up writing everything in notepad. Looking back at it now it makes sense. By manually writing the html you get a better understanding how it all fits together and it all gets demystified somehow. For me that is definetly my style of learning, take away all the supporting frameworks and start with what makes it tick. When you understand how it fits together, you could start looking at things that makes it faster/easier to use.

My next step was to use Flash (also a Macromedia product at the time). This was my first encounter with programming and I loved it. I did html and flash for a couple of years. I really enjoyed using Flash (particularly with AS3) and I used it on many projects to creating “functional” UI mockups. Then along came html5 and I started looking at other alternatives to create websites. I used Wordpress for a couple of years, then I did my own custom php cms soloution.

Then I started looking at static site generators. The first couple of years I used Jekyll. It worked ok, but since it is written in Ruby, which I dont use at all, I couldn´t really fully embrace it. Then, a few years later, after changing my main workstation, I thought I have a look for a new static site generator. Since I am really comfortable with Python I naturally tried Lektor, but since the forum around Lektor does not seem so active, I looked further and decided to try out Hugo, a static site generator written in Go. And I really like it, here are a few things I like:

  • Good documentation, forum and tutorials
  • A really nice CLI
  • Easy to setup custom pagination
  • Logical, robust and really fast
  • Syntax highlighting is included and easy to setup
  • The server with auto-load/refresh
  • Automatic TOC creation

Another benefit is since it is all static content, you can easily host it on Github pages. So this is the latest stop of my web journey. Below are some notes I took when getting to know Hugo!

List pages

Hugo will automatically create a list page for all 1st level subdirectories of the content folder. If you want Hugo to create list pages for deeper subdirectories we need to create a file called _index.md in that dir. we can also add content in this md file that will be displayed in the list page. If we want to add content to a first level subdirectory list page we can also create a _index.md file (note that the list ok age will be created regardless of this file)

Archetypes

Is the template used to control which front matter is created and populated when we run: hugo new page.md In the archetypes dir we find the default.md which is the default template used for new content. We can also create a specific template for content created in a specific content folder. The we call the archetype md file the same as the content dir.

Taxonomies

We can add the keyword tags and categories to our front matter and Hugo will create a list page structured based on the values. Tags and categories are the default taxonomies. If we want to use custom ones we need to specify this in the config.toml file

Templates

List and page templates templates for list and single pages are stored in a directory called _default in the layouts directory and are called list.html and single.html. The list and single page layouts stored in the _default directory are, as the name suggests, the template used by default for all single and list pages.

Section templates

But we can create special templates used for different content sections. These templates are called section templates. To do this we create a directory with the same name as the directory for the content we wish to create the template for. Lets say we have a directory called dir_c in the content directory. To create section templates for the content in this directory we create a directory in the layouts folder called dir_c. In the directory we can create list.html and single.html

Home page template

The home page is technically a list page so by default it uses a list template but we could give the home page its own template. We do this by creating a template in the root of the layouts folder called index.html

Base template

The base template are, as the name suggests, the template that are the base of all other templates. To create this template we create a file called baseof.html inside the _default directory inside the layouts directory.

<!DOCTYPE html>
<html>
<head>
	<title>{{ .Title }}</title>
</head>
<body>
	{{ block "main" . }}
	{{ end }}
</body>
</html>

And to use this baseof template we write the following (in the layout that we wish to implement the base template)

{{ define "main" }}

	The content will be rendered here...

{{ end }}

Note that we can use more blocks in the base template if we want. We can for instance create a footer and in the base template block add some default content that will be displayed if the block is not defined in the child template. If content is defined in the block (i.e. content is inserted inside the block when it is defined in the child template, it will be used and overwrite the default content)

Variables

Hugo’s templates are context aware and make a large number of values available to you as you’re creating views for your website. We can for instance use variables defined in the front matter, these are called page variables. To acces the title, date and url we use the syntax below.

{{ .Title }}
{{ .Date }}
{{ .URL }}

If we create some custom front matter variable we need to access it using the Params keyword.Lets say that we hava a key-value pair in the front matter specifying the_answer: 42. If we want to access it in the template we can use the following syntax:

{{ .Params.the_answer }}

Functions

To loop through the pages we can use the range function and provide the .Pages as the collection we wish to iteraste through.

{{ range .Pages }}
	{{ .Title  }}
{{ end }}

Partial

SVG

Using dict to pass multiple values to a partial The partial below creates a SVG and expects fill, height and width from the caller: hugo docs

Logic

Here is an example of how to use the if .. else if .. else We declare some variables (in a template) and display the result.

	{{ $a := 5 }}
	{{ $b := 1 }}

	{{ if eq $a $b }}
		(A) {{ $a }} is equal to (B) {{ $b }}
	{{ else if lt $a $b }}
		(A) {{ $a }} is less then (B) {{ $b }}
	{{ else }}
		(A) {{ $a }} is greater then (B) {{ $b }}
	{{ end }}

Note that the comparasion operators is not the “typical” ones like == instead we use:
eq ==
lt <
le <=
gt >
ge >=
and &&
or ||
not !=

If we use the and && statement it looks like this:

{{ $a := false }}
{{ $b := false }}

{{ if and ($a) ($b) }}
	{{ $a }} and {{ $b }} both are true
{{ else }}
	{{ $a }} and {{ $b }} one or none is true
{{ end }}

The or || operator looks like this:

{{ $a := false }}
{{ $b := false }}

{{ if or ($a) ($b) }}
	{{ $a }} and {{ $b }} one or both is true
{{ else }}
	{{ $a }} and {{ $b }} neither is true
{{ end }}

Data files

Lets loop through a json data file. We have the following json file in our data directory:

{
	"Batman":{
		"name":"Bruce Wayne",
		"universe":"DC"
	},
	"Ironman":{
		"name":"Tony Stark",
		"universe":"Marvel"
	},
	"Black Widow":{
		"name":"Natasha Romanova",
		"universe":"Marvel"
	}
}

To iterate through the data and print the name and universe inside an unordered list we can use this syntax:

<ul>
{{ range .Site.Data.superheros }}
	<li>{{ .name }} - {{ .universe }}</li>
{{ end }}
</ul>

If we want to also include the key (the superhero name in this case) we use this syntax:

<ul>
{{ range $key, $value := .Site.Data.superheros }}
	<li>{{ $key }} : {{ $value.name }} - {{ $value.universe }}</li>
{{ end }}
</ul>

Shortcodes

Shortcodes are a means to consolidate templating into small, reusable snippets that you can embed directly inside of your content.

Custom Shortcodes

To create a custom shortcode, place an HTML template (lets call it hello.html) in the layouts/shortcodes dir (create the dir if not present)

<!-- hello.html -->
<div>
	<h1>{{.Get 0}}</h1>
</div>

There are various ways of accessing parameters, in our case lets use a positional parameter. To acces the first parameter we use .Get(0) in our template.

To use the shortcode in a markdown file we do this. Note that the first part is the name of the template (minus the html extension) and the second part is our first positional argument.

{{ < hello world >}}

Note there must be NO whitespace between the curly-braces and the less/greater than sign.

Syntax highlighting

To generate a stylesheet using the monokai style you can run this:

hugo gen chromastyles --style=monokai > syntax.css

Run hugo gen chromastyles -h for more options. Here you will find a gallery of available styles.

I like using GitHub flavored code fences to add syntax highlighting. To enable this, set the pygmentsCodeFences to true in Hugo’s configuration file.

I also modified the highlight class in my main stylesheet to get the look I wanted:

.highlight{
	width: 100%;
	border-radius: 3px;
	background-color: #272822;
	margin-bottom: 15px;
	padding-left: 3px;
	padding-right: 3px;
}

Configure Markup

How to handle Markdown and other markup related configuration.

Images

To view an image generated from a markdown file I needed to add the following to the config.toml

canonifyURLs: true

Then I could use:

![](/images/pic.jpg)

Apparently The Markdown renderer has changed in the latest Hugo v0.62.0 from Blackfriday to Goldmark which should allow Hugo markdown to be more compatible with other markdown flavours, such as that of GitHub. So setting the blackfriday hrefTargetBlank to true did not work.

What did work was to create a template to render the links.

Create a file in layouts/_default/_markup/render-link.html with following content

<a href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener"{{ end }}>{{ .Text | safeHTML }}</a>

<!-- Internal link, with optional anchor -->
[Blender - notes](/notes/blender_notes/#regions)
<!-- External link -->
[Google](http://www.google.com)

More info here

Tips and Tricks

Increment variable & loops

Enumerated for loop

{{ range  $i, $e:= .Site.Data.banner }}
    <li data-target="#carouselExampleIndicators" data-slide-to="{{ $i }}" {{ if eq $i 0 }} class="active" {{ end }}></li>
{{ end }}

Increment value in loop

There might be a case where you can not use the index created by the foor loop. Lets say that you have a attrib called draft in your data file that you are looping through and the if the draft is set to false tou do not want to include it. In this case we need to manually increment $i when the attrib is true.

{{ $i := 0 }}
{{ range .Site.Data.banner }}
    {{ if not .draft }}
        <li data-target="#carouselExampleIndicators" data-slide-to="{{ $i }}" {{ if eq $i 0 }} class="active" {{ end }}></li>
        {{ $i = add $i 1 }}
    {{ end }}
{{ end }}

Jumping to Anchor

If I watch a good tutorial I usually take notes in blog form. I try to structure the notes to make it logical and easy to navigate. When running hugo server in dev mode the page reloads when the content is edited. This means that if you are working on some content at the bottom of a page, you need to scroll back down to preview. I added the snippet below so that the when the page reloads it automatically jumps to the anchor I specify (just remember to comment it out before publishing)

location.hash = "#volume-rasterize-attributes-velocity";