Up & Running With Hugo Part I: Building Your First Site

Up & Running With Hugo Part I: Building Your First Site

The popular static site generator written in GoLang - Hugo - has taken the community by storm. It brings all the benefits of a static site generator - 100% Flexibility, Security, Speed - but also steals the show otherwise πŸ‘‰ Hugo + Jekyll Benchmarked. In fact, the Forestry.io website is built with Hugo.

For this week on Frontend Friday, we’ll be covering how to get set up with Hugo on your local machine, including setting up a theme and customizing it, as well as writing your own CSS & JS.

How is this different from Hugo’s Quick Start guide? We’ll be using Hugo Boilerplate, a continuously maintained boilerplate project for Hugo sites that offers a modern developer workflow on top of Hugo.

Table of Contents

  1. Setting up Hugo on your local machine
  2. Adding Content & Installing a Theme
  3. Customizing Your Site
  4. Customizing Your Theme
  5. Next Steps

1) Setting Up Hugo

To get started, download the Hugo Boilerplate, and unzip the archive somewhere on your computer. You’ll also have to have Node.js and NPM installed, just follow the instructions on Node’s download page.

Hugo generates a project structure for you automatically. In the boilerplate project, this is the hugo/ directory. Inside of this directory are various folders containing your site’s content, layouts, and assets (e.g, CSS, JS, and images). Take a look at the breakdown of the boilerplates structure outlined below - I left out a few directories and files for clarity:

β”œβ”€β”€ hugo/                  // The Hugo project; content, data and static files
|   β”œβ”€β”€ .forestry/         // Contains Forestry.io configuration files
|   β”œβ”€β”€ content/           // Where all site content is stored
|   β”œβ”€β”€ data/              // TOML, YAML or JSON files containing site data
|   β”œβ”€β”€ layouts/           // Your site's layouts
|   |   β”œβ”€β”€ partials/      // Your site's partials
|   |   β”œβ”€β”€ shortcodes/    // Your site's shortcodes
|   β”œβ”€β”€ static/            // Where all static files live
|   |   β”œβ”€β”€ css/           // Where compiled CSS files live
|   |   β”œβ”€β”€ img/           // Where user images are stored
|   |   β”œβ”€β”€ js/            // Where compiled JS files live
|   |   └── svg/           // Where svg are stored
|   └── config.toml        // The Hugo configuration file
└─── src/
     β”œβ”€β”€ css               // CSS/SCSS source files to be compiled to /css/
     └── js                // JS source files to be compiled to /js/

To get the project up and running, open up a terminal window and navigate to the boilerplate folder (either hugo-boilerplate/ or hugo-boilerplate-master/):

cd path/to/hugo-boilerplate/

Then install all of the project dependencies by running:

npm install

To start the development server and open it up in your browser, simply run:

npm start
Want to get started without the Hugo Boilerplate - Check out our other guide.

2) Setting Up Your Site

To get started, we’re going to add new content to the site. To do so, we’ll need to update the content to the hugo/content/ folder.

Update A Post

To start, let’s update the example post shipped with the Hugo Boilerplate. Open up hugo/content/posts/example.md in your text editor. You’ll see title front matter field and some example markdown content.

title:  "Welcome to Hugo!"
You’ll find this post in your `content/posts` directory.

To add new posts, simply add a file in the `content/posts` directory that follows the convention `name-of-post.ext` and includes the necessary front matter. Take a look at the source for this post to get an idea of how it works.

Hugo also offers powerful support for code snippets:

    package main
    import "fmt"
    func print_hi(name string) {
      fmt.Println("Hi, ", name)

    func main() {
    //=> prints 'Hi, Tom' to STDOUT.
Check out the [Hugo docs][hugo-docs] for more info on how to get the most out of Hugo. File all bugs/feature requests at [Hugo’s GitHub repo][hugo-gh]. If you have questions, you can ask them on [Hugo Community][hugo-community]. [hugo-docs]: https://gohugo.io/documentation/ [hugo-gh]: https://github.com/gohugoio/hugo [hugo-community]: https://discourse.gohugo.io/

This post is missing a date! Try adding it by adding the following to the post’s Front Matter:

date: "YYYY-MM-DDTHH:MM:SS-00:00"
Replace YYYY-MM-DDTHH:MM:SS-00:00 with a valid date, e.g, 2018-01-01T12:42:00-00:00. If your date is in the future, Hugo wont build this post when doing production builds.

Save your changes and then view the updated post in your browser at http://localhost:3000/. The date in front of your “Welcome to Hugo!” post should have changed.

Create A New Post

Now let’s try creating a new post. We’ll use Hugo’s built-in commands to generate our new post. In the boilerplate, Hugo is added as an NPM dependency, so we can access it by running:

npm run hugo -- <command> --<param>

Create your first post by running:

npm run hugo -- new posts/my-first-post.md

This will create your new post at hugo/content/posts/my-first-post.md as a markdown file. Open this file in your favorite text editor.

title: "My First Post"
date: "2018-01-31T14:24:17-04:00"
draft: true

In this file, we have Front Matter (structured metadata for the page) that can be used in your templates. Below the front matter, we can add markdown content as well.

Try adding the following to the file and then save your changes.

## Hello world
Hi, I am the *Hugo Boilerplate*. I hope you are enjoying this guide!

You can view the updated post in your browser at http://localhost:3000/posts/my-first-post/.

Adding A Theme

Right now your new site isn’t looking very pretty. Let’s fix that by adding a pre-built Hugo theme from the Hugo Theme Gallery, built by one of Hugo’s great community contributors.


We’re going to use the Casper theme by @vjeantet. We’ll do this by adding the theme to the hugo/themes/ directory, specifically hugo/themes/hugo-theme-casper/. You’ll have to add these inside your hugo/ directory.

Download the theme, unzip the archive and then copy the entire contents to hugo/themes/hugo-theme-casper/.

Next, you’ll need to update your site’s configuration with any of the theme-specific configurations.

Open hugo/config.toml in your favorite text editor, and replace the contents with the following:

baseURL= "/"
languageCode= "en"
title= "Hugo Boilerplate"
paginate = 5
copyright = "All rights reserved - 2018"
theme = "hugo-theme-casper"
disableKinds = ["taxonomy", "taxonomyTerm"]

  description = "Welcome to my website"
  metadescription = "Used as 'description' meta tag for both home and index pages. If not set, 'description' will be used instead"
  cover = ""
  author = "YOUR_NAME"
  authorlocation = "Earth, Milky Way Galaxy"
  authorwebsite = ""
  authorbio= ""
  logo = ""
  hjsStyle = "default"
  paginatedsections = ["posts"]

For a full list of available configuration docs, see the theme documentation.

Finally, the boilerplate comes with some example layouts for developers that are building from scratch. Let’s remove these for now by running:

rm -r hugo/layouts/

Now head back over to the browser and check out your updated site!

3) Customizing Your Site

Now that we’ve set up a basic working site with a theme, you’ll probably want to personalize it.

First, we’ll customize the site params. Open up hugo/config.toml once more, and update the following as you see fit:

  • title = "Hugo Boilerplate"
  • description = "Welcome to my website"
  • metadescription = "Used as 'description' meta tag for both home and index pages. If not set, 'description' will be used instead"
  • author = "YOUR_NAME"


Next, we’ll update the default hero image to something else. Open up hugo/config.toml and find \[params\]. Below, find the parameter cover and update it to /img/darius-soodmand-116253.jpg, and save your changes.


Now head back to your browser to see your updated site. It won’t look exactly like the screenshot above but don’t worry we’ll get there.

4) Customizing Your Theme

Now that you’ve customized your site to be a little more personalized, we’ll focus on the most powerful aspect of Hugo and this boilerplate: powerful yet simple templating.

Earlier we added the Casper theme to the site, which allows Hugo to use all of the HTML layouts stored at hugo/themes/hugo-theme-casper/layouts/ to generate your site.

Now, we’ll extend the theme by using Hugo’s template inheritance.

Any layouts stored in hugo/layouts/ will override any layout with the same name in theme’s layouts directory, allowing us to customize our site without messing with the theme.

Custom CSS & Javascript

Along with Hugo, this boilerplate comes with a development server that automatically post-processes CSS & JS for the browser. Any CSS, JS, or images found in the src/ folder will be processed and automatically moved to hugo/static/.

Let’s add these to your theme so that you can customize it as needed. We’ll copy the base layout of the theme and add the boilerplate’s custom CSS and JS files to the layout.

First, we’ll copy the header partial of the theme to the hugo/layouts/partials/ directory:

mkdir -p hugo/layouts/partials/
cp hugo/themes/hugo-theme-casper/layouts/partials/header.html hugo/layouts/partials/header.html

Open hugo/layouts/partials/header.html in your favorite text editor and find the following:

<link rel="stylesheet" type="text/css" href="{{ "css/screen.css" | relURL}}" />
<link rel="stylesheet" type="text/css" href="{{ "css/nav.css" | relURL}}" />

Below this add:

<link rel="stylesheet" type="text/css" href="{{ "css/styles.min.css" | relURL}}" />

Next, we’ll copy the partial footer.html to the hugo/layouts/partials/ directory so we can add our custom JS:

cp hugo/themes/hugo-theme-casper/layouts/partials/footer.html hugo/layouts/partials/footer.html

Open hugo/layouts/partials/footer.html and find the following:

<script type="text/javascript" src="{{"js/jquery.js" | relURL}}"></script>
<script type="text/javascript" src="{{"js/jquery.fitvids.js" | relURL}}"></script>
<script type="text/javascript" src="{{"js/index.js" | relURL}}"></script>

Below this add:

<script type="text/javascript" src="{{"js/scripts.min.js" | relURL}}"></script>

Now all of your custom CSS and JS will be used on the site.

Let’s give it a try by expanding the height of the main header. Open src/css/styles.css and adding the following to the bottom of the file:

.tag-head.main-header {
  height: 80vh;


Head back over to your browser to see the final result!

5) Next Steps

Now you’re all set to begin building your static site with Hugo!

Feel free to continue using the Casper theme, or start from scratch using the hugo/layouts/ directory.

Check out the example files in the Boilerplate repository if you choose to start from scratch.

Check out the following further reading to learn more about Hugo:

Up next

Next week we’ll be releasing a post on setting up version control with Git to facilitate continuous integration and continuous deployment to various hosting providers using Forestry, the CMS for static sites built with Hugo and Jekyll.

Join us every Friday πŸ“…

Frontend Friday is a weekly series where we write in-depth posts about modern web development.

Next week: Up & Running with Hugo Part II: Continuous Integration & Continuous Deployments

Last week: We looked at integrating a performant search into your static site: Static search with Hugo + Algolia .

Have something to add?

Discuss on Hacker News