A quick tutorial on Hugo templates and creating your theme

Giacomo Mariani
Level Up Coding
Published in
5 min readDec 15, 2020

--

This quick hands-on tutorial helps in understanding the logic behind Hugo themes and templates. We will create our own website and theme from scratch, and see how the different template layouts interact with each other and the content.

Create the structure for our new website with the hugo new site command:

Creating a new site by executing the hugo new site command
Creation of a new Hugo site with “hugo new site” command

As you can see, we have two options: using a ready theme or creating our own. I think that the best way to grasp how all the different layouts and content files interact is to create our own theme and work our way through. We start with the hugo new theme command:

Creating a new theme with the “hugo new theme” command
Creation of a new theme with the “hugo new theme” command

The command creates a new empty theme, with the folder structure and necessary files.

Folder structure of myTheme folder
Folder structure and content of the recently created theme

If we start the server with thehugo servercommand, we get some warnings like the one shown below (we’ll get back to that soon). Then, if we go to localhost:1313 we get a blank page, so it is working but we have no content. Let’s see which layout files are being used and how.

Part of the terminal output when executing the hugo server command
The hugo server command

Before continuing though, we have to tell Hugo that we are now using our myTheme template, so it knows where to look for the layouts template files. We can do this in the config.toml file at the root of our project. Just add the theme line and change the name of the theme in case it is called something else:

baseURL = “http://example.org/"
languageCode = “en-us”
title = “My New Hugo Site”
theme = “myTheme”

baseof.html

The Hugo documentation explains that

baseof.html is the shell from which all your pages will be rendered unless you specify another *baseof.html closer to the beginning of the lookup order.

So this is what Hugo used as the base for all our pages. Lets’ see the content of our themes/myTheme/layouts/_default/baseof.html:

Content of the base.html file
Content of the base.html file

base.html pulls the content from the head.html, header.html, and footer.html partial templates found in the myTheme/layout/partial folder. It also pulls the content from the main block.

The main block comes from an html template, and the template used depends on the type of page.

The blank landing page for example, where does its content come from? That blank page is our Homepage, which Hugo considers as an own type of list page. Like other list pages, it is formed out of a template HTML file giving the structure, and a Markdown file with the content, which we explore next.

Homepage

For the Homepage we need:

  • layouts/index.html
  • content/_index.md

The layouts/index.html file for our theme is under themes/myTheme/layouts/index.html, and it is empty. We can fix this using the example template given in the Hugo documentation and adding it to our theme’s index.html file:

What happens here? Hugo is pulling the title (line 4), subtitle (lines 4–6), and content (line 10) from the _index.md file, and the template for the summary of all pages under the Homepage (lines 13–15).

Now that we have the structure, we still miss the Homepage content.

The content folder structure and organisation reflects how the site is rendered. Its subfolders give the page path, determine content Type, and therefore the layout being used.

The content for the Homepage is pulled from content/_index.md file, which we are still missing, so let’s add it. Create the _index.md file under the content folder and add this content to it:

---
title: "Homepage"
subtitle: "Here I am"
date: "2020–012–09"
menu: "main"
draft: "false"
---
Hello World!

What you see above between the dashed lines is called the Frontmatter, and it contains metadata for the page. It can be used, among other things, to specify a specific type or layout for overriding the default ones.

Now, if you have saved the changes and Hugo server is still running, you should be able to see the content of the Homepage at localhost:1313.

Single pages (blog posts or other)

For our blog post we need:

  • content/post/first-post.md
  • layouts/_default/single.html
  • restart the server

We continue by adding a blog post, but the same procedure is valid for any type of single page you want to create. Create a new blog post by executing in the terminal hugo new post/first-post.md. The command will add the content/post folder, and the first-post.md file to it, with a ready Frontmatter. In the Frontmatter, change draft: false to draft: true , otherwise, Hugo will not show the post when using the normal hugo server command. To build and serve also drafts, you would have to use hugo server -D.

Next, we add the html template for single pages to our myTheme in layouts/_default/single.html . We can copy the template from Hugo documentation:

Stop the Hugo server with Ctrl+c and then restart it executing hugo server. Now you should see your blog post from http://localhost:1313/post/first-post/.

As you can see from the URL and path of your post, Hugo takes the path from the folder name, and the slug from the file name.

List pages

For the list page we need:

  • content/post/_index.md
  • layouts/_default/list.html

List pages can be useful if you want for example to list your posts on one page or list the content of any other section. In our case, we want a page in http://localhost:1313/post, that lists all our blog posts.

Create the content/post/_index.md file from the terminal executing thehugo new post/_index.md command and change draft to false. Also, add some text after the dashed lines:

---
title: "Post"
date: 2020-12-13T07:41:10+02:00
draft: false
---
Have a look at my blog posts!

Next, add the template to myTheme in layouts/_default/list.html , we can again use the Hugo documentation for this:

Now the localhost:1313/post/ should show you the post-page with your blog post listed.

Conclusion

This was just an introduction to using Hugo themes and templates. There is much more to it, but now that you have an understanding of the logic, I think you can take full advantage of the Hugo documentation. Go ahead, add more content, links, and images (check this and this) to your site!

There is still one little caveat. Do you remember this block from the layouts/index.html file in myTheme?

{{ range first 10 .Site.RegularPages }}
{{ .Render "summary"}}
{{ end }}

Why it is not showing the summary of the blog post? Check this out and see if you can fix it!

--

--