On Static Site Generator - Hugo

Over the last few weeks, I've been looking into a Static Site Generator - Hugo. A Static Site Generator is useful if you're building an application which does not require dynamic data to be served. A blog can be considered as a service which serves static content. Instead of storing the content in a database field, the content is stored in a file (HTML file). Thus when a page is requested the content is served immediately instead of it being generated on demand; resulting in accelerated response times and thus better user experience.

Hugo helps in generating a static site. It has got several features such as defining layouts for various types of content, displaying a list of related content, tagging content (taxonomies), using themes and also generating content from data in JSON, YAML or TOML files.

Hugo provides a Command Line Interface to generate content. After installing Hugo (brew install hugo), create a new site using the command

hugo new site hugo_bootstrap_example 

Hugo creates a directory structure as detailed below:


All content should be present in the 'content' directory. If you are considering to build a blog, then this directory would contain all the blog posts. To create a new post use the command:

hugo new posts/blog-post-1.md

This will create a markdown file blog-post-1.md under 'content/posts' directory. The directory 'posts' is created if it doesn't exist. When you open the file, you'll notice that it contains some meta-data in it, it's called front matter. By default the front matter contains 'date' and 'title',  here date being the created date and title being the file name:

date = "2016-12-04T16:13:35+05:30"
title = "blog post 1"


The front matter is enclosed in +++, any text that follows after the last '+++' will constitute the content or the body of the post. Hugo organises the output in the same way as it is declared i.e. to view the post you can access the URL <site>/post/blog-post-1. This can be changed by updating the front matter to include section, path and slug fields (more on this in the next post).

On Layouts:

Once you have defined the type of content that you want to render, you need to define how this content will be rendered. For example, if you have created two different types of content - 'posts' and 'pages' then you need to define views for 'posts' and 'pages' in the 'layouts' directory. This is required because Hugo does not know how to render the content. It took me some time to understand how Hugo does this; it looks up for templates defined in the layout directory and generates static files based on the number of files present in the 'content' directory. This also means that if you have defined content but the corresponding layout is missing, then no static file is generated for that type of content.

Note: If you would like to use the same layout for all types of content, then create a directory '_default' under layouts and then define the view templates under it.

Let's create a template for 'posts':


Here single.html is a template file, that defines how the post would look like when the user accesses the URL <site>/posts/blog-post-1. In addition to displaying the title and the content of the post, you can display the date on which the post was published:

<!DOCTYPE html>
  <title>{{ .Title }}</title>
    <a href="{{ .Permalink }}">
      {{ .Title }}
  {{ .Content }}
  <h6>Published on: {{ .Date.Format "Mon 2, Jan 2016" }}</h6>

Hugo uses GO templates to generate the content. In the above example, 'Title', 'Permalink', 'Content' and 'Date' are template variables, which are used to generate static files based on the front matter and the content defined in the file 'blog-post-1.md'.

In addition to defining single post view, you can also define a list view (li.html) - a view to display a list of content posts instead of one single post and a summary view (summary.html) - to view only a part of the content.

Rendering the site using Hugo server:

Before we get to rendering the content on the browser, Hugo requires some configuration to display the content. This configuration contains site information such as the 'baseUrl', 'title', 'languageCode' and 'theme'. When you generate the site, you'll have the file 'config.toml' created, which contains the above configuration fields. All that is required is to provide the values for the above fields. Here's the example 'config.toml' file content:

baseurl = "localhost:1313"
title = "My New Hugo Site"
languageCode = "en-us"
theme = "ex_bootstrap_theme"

Hugo comes with a built-in web server and you can start it using the command:

hugo server

It starts the server at port 1313 and you can try the URL localhost:1313. This command will generate the static content and will watch for the file changes in directories generated by the hugo new site command.

On Themes:

A Theme, like Layouts, is used to define templates. There's not much difference between a theme and a layout, except that a theme should be created if you want to reuse it for a different site. This will enable you to encapsulate the look and feel of the site along with behaviour (JavaScript) and share it with others who can then follow the same convention to build the site.

I'm inclined towards using a theme over layouts only for the sole reason that it can be shared with other users.

Hugo does not ship with a default theme, however, a theme is required to run the server. You can download one of the many themes available at http://themes.gohugo.io/ or create your own theme using the command:

hugo new theme <theme_name>


I really liked Hugo and I'm getting used to GO templates. There are tonnes of options available to customise the site and I'm still exploring these options. The biggest selling point is it's performance when generating static content. I haven't tested the site containing several pages, but it takes say about 12ms to generate a very small site with 4 pages in it, which is extremely fast.

Hugo does not dictate how your site should be styled, however, it provides a directory 'static' where all your CSS, Images and JavaScript files should be placed.


Popular posts from this blog

Custom validation messages for HTML5 Input elements using the constraint validation API

JavaScript debugging with Chrome Developer Tools and some tips\tricks

File upload and Progress events with HTML5 XmlHttpRequest Level 2