Getting started with Hugo: Customize Website

Almost all customizations for Hugo websites can be done using configuration. The configuration is stored in the single place the hugo.yaml file at the root folder of the website. Hugo comes with the hugo.toml (TOML) but I prefer to use YAML for my configurations. Hugo also supports JSON if you like it more.

Documentation is nice and descriptive. I found several guidelines about what should be included into the config file. The following is my experience with the configuration, a couple of “learned lessons” and the list of settings I found useful. While I write it here in some creative chaotic order, in the file I ordered all of them alphabetically so it is easy for me to find if I just scroll through.

Top settings

In the first post I ended with theme configuration. To setup the website to use a particular theme, add the following configuration:

theme: "mainroad"

You just place the name of the folder under “themes/”, in my case “mainroad”, as a value. If I run “hugo server” now I will see the same site but using the Mainroad theme.

Next, or maybe it had to be the first thing, let’s configure the blog title. This is super important 🙂.

title: "My blog title"

Last of the top-level configurations that I want to mention is baseURL. Some guidelines recommended to place "/" as its value. If you do, your website will not work locally. The doc states that you have to place “URL of your published site”. The dummy value of “” workes for me so far. However, I will change it to my personal domain after I finish with all deployment activities.


Majority of settings are placed under params configuration. You might want to setup logo:

    image: "site_logo.pmg"

The path to the logo’s image has to be relative to the static/ folder. Another parameter, “sidebar”, controls what you show on the side of your content. Control the layout of the sidebar and widgets inside.

    home: "right" # Configure layout for home page
    single: false # Configure layout for single pages
    widgets: ["search", "recent", "taglist", "social"]

If you decided to show widgets of your social networks in the sidebar, you configure them separately:

      - icon: "svg/medium.svg"
        rel: "noopener noreferrer"
        title: "Medium"
        url: "" 

Configuration supports main social networks (e.g. facebook, linkedin, etc.) out of the box. You can also customize other entries, like Medium. One caveat is the location of the SVG icon for custom social widgets. The path is related to the folder layouts/partials in your current theme. My theme has the svg subfolder where I copied to the Medium SVG icon.

I am not going into too much detail about menus. In my blog I decided to have only the main menu with a fixed number of entries. This menu is configured like the following:

  - name: Home
    pageRef: /
    weight: 1
  - name: About
    pageRef: ""
    weight: 1000

The “main” menu is one shown at the top of the pages under the title and subtitle of the blog. My “main” menu has two items: “Home” and “About” that take a user to the root of the blog or to the page that talks about the author and the blog. The weight parameter allows you to control the order of menu items when dynamic composition of the menu is configured or when certain pages are added to the menu.

Last modified date

I wanted to distinguish between the last modified and creation date and to have the last modified date to pick up from the last commit that modifies the file. The Hugo settings that let me do that are pretty straightforward:

enableGitInfo: true
  date: ["date", "publishDate", "lastmod"]
  lastmod: ["lastmod", ":git", "date", "publishDate"]

You can read more about these settings in Hugo docs.

Other customizations

I made a few small customizations to the Mainroad theme. By default the theme shows the post date in the form of “<creation date> (Last modified: <modified date>)”. The display of the date is controlled by post_meta parameter and the format by dateformat in the params section. I wanted to have only one date to be displayed: create date if the post is new or the modified date, if the post was modified later. After refreshing my knowledge about template scripting I ended up with this version:

{{ if not .Date.IsZero }}
<div class="meta__item-datetime meta__item">
  {{ partial "svg/time.svg" (dict "class" "meta__icon") }}
  {{ if and (not .Lastmod.IsZero) (lt .Date .Lastmod) }}
  <time class="meta__text" datetime="{{ .Lastmod.Format " 2006-01-02T15:04:05Z07:00" }}">
    {{ T "meta_lastmod" }}: {{ .Lastmod | dateFormat (.Site.Params.dateformat | default "January 02, 2006") }}
  {{ else }}
  <time class="meta__text" datetime="{{ .Date.Format " 2006-01-02T15:04:05Z07:00" }}">
    {{ .Date | dateFormat (.Site.Params.dateformat | default "January 02, 2006") }}
  {{ end }}
{{ end }}

The widget for the date in the Mainroad theme is stored at themes/mainroad/layouts/partials/post_metadata.

* * *

I wish I could give a reference to my full configuration file. But I manage the repository with my blog as a private Github repo 🤷. So, let’s talk about hosting decisions.