In this post, we will see how we can create and configure our Hugo blog to our needs. This guide assumes, that Hugo is already installed in your system.

We will use a certain theme as an example, but the same principles apply to almost every theme.

We must also note that Hugo is somewhat tied to the theme you have, so if you want to change it, some changes will need to be made, mostly on the top config file, and less on the markdown content.

Create a Site

Create a new site with the name TestSite:

hugo new site TestSite

and change directory in the newly created directory:

cd TestSite

If you list the directories it should have the following structure:

user@hostname ~/TestSite$ ls -l
archetypes
config.toml
content
data
layouts
resources
static
themes

Archetype Configuration

In the archetypes/default.md file there are the default metadata generated when creating a new page. The default are:

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

We can change the draft option to false, in order to publish all new posts:

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

Initialize Git repo

Initialize a Git repository in order to keep changes and have version control, by executing inside the site directory:

git init
git add .
git commit -m "First commit"
git branch -M main

Download & Install a Theme

Find a theme

Find a theme in the Hugo Themes page and download it from GitHub.

Download a theme

For example if we choose the hyde-hyde theme, the Download button redirects us to its GitHub page. We can then copy the HTTPS link for cloning and instead of cloning it directly in the themes directory, we add it as a submodule in order to be able to fetch new changes and updates from the repo:

git submodule add https://github.com/htr3n/hyde-hyde.git themes/hyde-hyde

Update config file

Then, add the theme to the site configuration:

echo theme = \"hyde-hyde\" >> config.toml

Add a Post

We can manually create content files, that follow this format content/<CATEGORY>/<FILE>.<FORMAT>, and give them metadata using the new command:

hugo new posts/my-first-post.md

And add some content to the page using MarkDown:

echo "# My First Post \nThis is my first post." >> content/posts/my-first-post.md

Edit config file

Usually themes come with an exampleSite directory that contains a basic example site and its config file. We can open it to configure the theme based on this:

cat themes/hyde-hyde/exampleSite/config.toml

or we can replace it completely as we have nothing important yet and we can select what configuration we want to keep:

cp themes/hyde-hyde/exampleSite/config.toml .

Add a Page

Create a page for the site, e.g. the About page:

hugo new about.md

And add some content to the page using MarkDown:

echo "# About \nThis is the about page." >> content/about.md

Configure the Menu

Configure themes (Style)

Create a new style.css in the static directory of the site, like:

vim static/style.css

and add any custom css rule you want from the theme, like:

body.dark-theme {
  /* dark theme colors */
  --background: #292a2d;
  --header: #59114f;
}

this way we don’t have to build the theme.

Categorize Posts

Hugo has the feature of taxonomies that support two basic ones: tags, categories. We can use these 2 default ones, or we can create new taxonomies by defining them in the config.toml file.

In order to populate the categories taxonomy, in every post’s front matter you add the following for yaml front matter:

categories:
  - Development
  - Scripting

and for toml front matter:

categories = ["Development", "Scripting"]

The next thing we need is a template that Hugo will use to display the /categories page. We can place this template in the layouts/_default directory and add a terms.html template. Usually the themes provide one that we can use, so we can copy it:

mkdir layouts/_default
cp themes/hello-friend/layouts/_default/terms.html layouts/_default

Syntax Highlighter

Hugo uses Chroma as the default syntax highlighter. In order to configure it we have to add this option to config.toml:

pygmentsUseClasses=true

Then in order to generate a new style for Chroma, we use the following command:

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

we can find all the available styles at the Chroma Style Galler.

Create Social Icons Layout

We will create a new social media icon layout that is used by some themes. We will create a social-icons.html template in layout/partials:

mkdir layouts/partials
touch layouts/partials/social-icons.html

and we will add the following:

{{ range . -}}
<a
  href="{{ .url | safeURL }}"
  target="_blank"
  rel="noopener me"
  title="{{ .name | humanize }}"
  style="margin-left:0.5em"
  >{{ partial "svg.html" . }}</a
>
{{- end -}}

This template takes all the parameters from the main configuration file (config.toml) and creates an svg list with the corresponding icon names in the layouts/partials/svg.html file.

We can edit config.toml in order to specify which social icons we want:

[params]

# ...

  # Social Icons
  [[params.social]]
    name = "github"
    url = "https://github.com/"

  [[params.social]]
    name = "twitter"
    url = "https://twitter.com/"

  [[params.social]]
    name = "linkedin"
    url = "https://www.linkedin.com/"

Then we will create the svg.html template in layout/partials, that will have all the svg icons based on the name of the social app:

touch layouts/partials/svg.html

and we will add the following:

{{- if (eq .name "codepen") -}}
<svg
  xmlns="http://www.w3.org/2000/svg"
  class="feather"
  width="24"
  height="24"
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
>
  <polygon points="12 2 22 8.5 22 15.5 12 22 2 15.5 2 8.5 12 2"></polygon>
  <line x1="12" y1="22" x2="12" y2="15.5"></line>
  <polyline points="22 8.5 12 15.5 2 8.5"></polyline>
  <polyline points="2 15.5 12 8.5 22 15.5"></polyline>
  <line x1="12" y1="2" x2="12" y2="8.5"></line>
</svg>
{{- else if (eq .name "facebook") -}}
<svg
  xmlns="http://www.w3.org/2000/svg"
  class="feather"
  width="24"
  height="24"
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
>
  <path
    d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"
  ></path>
</svg>
{{- else if (eq .name "github") -}}
<!-- ... -->

Now we can use this template in another layout we want. We want to add a list of social media icons in our footer, so we copy the themes footer.html template in layout/partials:

cp themes/hello-friend/layouts/partials/footer.html layouts/partials

and we can add it anywhere we want like this:

{{- with .Site.Params.social }}
<div id="social-icons">{{ partialCached "social-icons.html" . }}</div>
{{- end }}

Create Social Icons Shortcode

If we want to use the same social media icons template in a specific page e.g. the About page, we can create a custom shortcode that has the same function as the social-icons.html layout.

We will first create a new social media icon shortcode. We will create a social-shortcode.html template in layout/shortcodes:

mkdir shortcodes
touch layouts/shortcodes/social-shortcode.html

and we will add the following:

<div id="socials">
  {{ range $.Page.Site.Params.social -}}
  <a
    href="{{ .url | safeURL }}"
    target="_blank"
    rel="noopener me"
    title="{{ .name | humanize }}"
    style="margin-left:0.5em"
    >{{ partial "svg-large.html" . }}</a
  >
  {{- end -}}
</div>

It is the same function but we just wrap the link tags with a div because we will use it directly in the Markdown content.

We will also create optionally a new svg.html file that will have the same icons but with larger dimensions, so we create the svg-large.html template in layout/partials:

touch layouts/partials/svg-large.html

and we will add:

{{- if (eq .name "codepen") -}}
<svg
  xmlns="http://www.w3.org/2000/svg"
  class="feather"
  width="56"
  height="56"
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
>
  <polygon points="12 2 22 8.5 22 15.5 12 22 2 15.5 2 8.5 12 2"></polygon>
  <line x1="12" y1="22" x2="12" y2="15.5"></line>
  <polyline points="22 8.5 12 15.5 2 8.5"></polyline>
  <polyline points="2 15.5 12 8.5 22 15.5"></polyline>
  <line x1="12" y1="2" x2="12" y2="8.5"></line>
</svg>
{{- else if (eq .name "facebook") -}}
<svg
  xmlns="http://www.w3.org/2000/svg"
  class="feather"
  width="56"
  height="56"
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
>
  <path
    d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"
  ></path>
</svg>
{{- else if (eq .name "github") -}}
<!-- ... -->

w we can use this template in any page we want. We want to add a list of social media icons in our About page, so we open:

vim content/about.md

and we can add the shortcode, using the name of the files without the .html suffix: