DEV Community

Cover image for Blogging in Hugo
David Large for CloudCannon

Posted on • Updated on • Originally published at cloudcannon.com

Blogging in Hugo

By Mike Neumegen

Brought to you by CloudCannon, the Git-based CMS for Hugo.

A blog in Hugo is relatively straightforward. It consists of a page that lists all the blog posts, and a series of content pages with a date for the posts. That’s all there is to it.

Creating a blog list page

You’re going to see how the layouts hierarchies work with this example.

Create a directory called posts in your /content/ directory, and inside that, create a file called _index.md with the following:

    ---
    title: Blog
    ---
Enter fullscreen mode Exit fullscreen mode

_index.md — remember what that means? It’s a table of contents file, and in this case it will be listing your posts. At the moment, it’s going to try to use the /layouts/_default/list.html layout. You don’t want to use this layout as this page doesn’t have any content. Instead, you’ll want to create a new layout specifically for listing posts.

The way the Hugo layout hierarchy works is it will first look for a layout that matches the current section (think of section as the directory), then fall back to the global default in _default. In other words, we can create a new directory called posts in the layouts directory, and inside create list.html with the following content:

    {{ define "main" }}
      <h1>My posts</h1>
      <ul>
      {{ range .Pages }}
        <li>
          <a href="{{ .Permalink }}">{{ .Title }}</a> - {{ .Date.Format "January 2, 2006" }}
        </li>
      {{ end }}
      </ul>
    {{ end }}
Enter fullscreen mode Exit fullscreen mode

There are few new concepts here; let me explain.

  1. A list page (_index.html) has an array of all its children pages with the variable .Pages.
  2. .Date has format called on it and gets passed a random date in 2006. Why is that? It’s a quirk of Go for formatting dates. You can read more about it here.
  3. .Permalink can be called on any page to get its end URL. It’s particularly useful if you want to link to a page.

That’s all we need for our list page. Let’s move onto a post.

Creating a post

We’ve already done the hard part. Let’s get this blog finished by creating a few posts.

The posts live in the /content/posts directory and don’t require any special naming convention. One tip I like to encourage is adding the date of the post to the file name. Hugo will completely ignore it, but it helps when you have find a post amongst hundreds of others.

Let’s create three blog posts to get you started.

/contents/posts/2022-04-03-i-like-to-roar.md

    ---
    title: I like to roar
    date: 2022-04-03
    ---
    Hi, quick update from me. I just want to let everyone know that I like roaring.
Enter fullscreen mode Exit fullscreen mode

/contents/posts/2022-04-02-today-i-made-friends.md

    ---
    title: Today I made friends
    date: 2022-04-02
    ---
    I got lost in the woods today. Two friends, a Meerkat and a Warthog, found me, sung a song with me and gave my life new meaning. Today was a good day.
Enter fullscreen mode Exit fullscreen mode

/contents/posts/2022-04-01-vegan-experiment.md

    ---
    title: Vegan experiment
    date: 2022-04-01
    ---
    I tried to become a vegan today. I made it to lunch time and couldn't bear the sight of another green leaf. Yuck!
Enter fullscreen mode Exit fullscreen mode

Just like the blog list page, these posts will try to use /layouts/_default/single.html. Let’s create a layout specifically for posts at /layouts/posts/single.html with the following:

    {{ define "main" }}
      <h1>{{ .Params.Title }}</h1>
      <p>{{ .Date.Format "January 2, 2006" }}</p>
      {{ .Content }}
    {{ end }}
Enter fullscreen mode Exit fullscreen mode

Finally, let’s add the blog to the navigation. Open /layouts/partials/nav.html and add another item:

    <li><a href="/posts/">Blog</a></li>
Enter fullscreen mode Exit fullscreen mode

Run hugo serve, open the site in a browser and view your masterpiece.

What’s next?

In our final lesson, we will use Hugo Data files to populate a map with your favorite vacation spots.

Top comments (0)