Hugo is a flexible way to generate static sites. Many people reach for premade themes/templates, but some people (like me!) want to create their own. There’s a lot to learn about Hugo and it can be daunting to take it all in at once.
This post is a beginner’s checklist for learning Hugo. This picks up right after you’ve completed the Hugo Quick Start Guide.
By learning just these concepts, you should be able to create a website with a home page, a blog, and other specialized content without having to rummage through all the docs. The rest of the docs will come into play once you’re looking to create more advanced content.
To get you started, I’ve provided working examples of each type of file.
With few exceptions, you should be extending a base template for all the
templates you create. A base template usually defines the outermost layer of
each page. The <html>, <head>, and <body> tags are in this file.
The base template defines a number of sections. When templates extend a base
template, they provide the content to fill these sections. Sections start with
{{ block "my-block-name" . }} and end with {{ end }}.
You should create a base template in layouts/_default/baseof.html that’s used
by all your other templates. To start, you’ll want to have a main section where
the primary content of the page lives. You’ll also want to have a title section
so that individual pages can set the title of the page.
The base template could look like this (layouts/_default/baseof.html):
<html>
<head>
<title>
<!-- Default to the name of the site if a title isn't provided -->
{{ block "title" . }}
{{ .Site.Title }}
{{ end }}
</title>
</head>
<body>
{{ block "main" . }}
<!-- Templates will fill this content -->
{{ end }}
</body>
</html>
We’ll use this base template when creating “list” and “page” templates in this checklist.
List pages typically give an overview of a particular type of content. For example, going to the “news” section of a website might show you snippets of text for each news post on the site.
This can get fairly elaborate. For example, you could have a list of courses, and each course could be a list of lessons.
Here’s a basic list page template that uses the base template from above (layouts/_default/list.html):
{{ define "title" }}
{{ .Page.Title }}
{{ end }}
{{ define "main" }}
<h1>{{ .Page.Title }}</h1>
{{ .Content }}
<ul>
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">
{{ .Title }}
</a>
</li>
{{ end }}
</ul>
{{ end }}
You can see we use range to iterate over each piece of content, and we’re
grabbing the name and url of the content. To get a short summary of the content
of the page, you can use the {{ .Summary }} property. This is autogenerated,
but can be specified manually in various ways.
For content in content/posts, you can see the list page for that content at
https://yoursite.com/posts.
To customize this page, you can create a _index.md page at content/posts/_index.md.
The rendered text from that markdown file is available to the list page template
as .Content.
If you want to create a new template specifically for your posts (rather than
using the default), you can create a new template at layouts/posts/list.html.
Your homepage is also a list template and will use the default template if you
don’t provide one. Alternatively, you can specify one explicitly in layouts/list.html.
Single pages are your pieces of content, whether that’s a blog post, tutorial,
or article. Hugo allows you to attach YAML data to content. This lets you
associate things like videos or a hero image with your content. Those bits of data
are accessible to the single page template. Hugo capitalizes the property name,
so prop becomes Prop.
At it’s most basic, a single page should probably show the title of the content and the text from the content.
Here’s a basic one you could use as a default (layouts/_default/single.html):
{{ define "title" }}
{{ .Page.Title }}
{{ end }}
{{ define "main" }}
<div class="prose">
<h1>{{ .Page.Title }}</h1>
{{ .Content }}
</div>
{{ end }}
You’ll see that I wrapped the contents in a div with class prose. This makes
it easy to create CSS that just targets the contents of the page, but doesn’t
affect the templates. The HTML tags that Hugo generates don’t have any classes
you can hook on to, so you need to provide something to select on in your CSS.
If you want to create a template specifically for your posts, you can create a
new template at layouts/posts/single.html. This allows you to display your
posts differently than tutorials, news items, etc.
For site-wide static files (images, css, js), put them in the static directory.
Now those files are accessible at the base of your site (E.g.https://yoursite.com/yourfile.foo).
From there you could to link your CSS it in your base template (layout/_default/baseof.html)
with <link href="/yourstyle.css" rel="stylesheet">.
It’s helpful to know in detail where templates can go, and how to find out which template is being used for which bit of content. This page will break that down (and where the home page template goes!).
Understanding how to create content and templates is the backbone of Hugo. Once you understand these basics, you can start to branch out. Hugo has a bunch of special features for common things for websites.
If you want a robots.txt and a sitemap for SEO, Hugo has you covered. Search
bar? Yup! Tags on your blog post? Sure. Hugo also has a bunch of functions you
can call from your templates.
Remember to check out the Hugo Showcase to see the awesome sites folks have made!