Skip to main content

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:

--archtypes
--content
--data
--layouts
--static
--themes


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':

--layouts
  --posts
    --single.html


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>
<html>
<head>
  <title>{{ .Title }}</title>
</head>
<body>
  <h1>
    <a href="{{ .Permalink }}">
      {{ .Title }}
    </a>
  </h1>
  {{ .Content }}
  <h6>Published on: {{ .Date.Format "Mon 2, Jan 2016" }}</h6>
</body>
</html>


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>

Summary:

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.

Comments

Popular posts from this blog

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

HTML5 has introduced several input types such as EMAIL, URL, RANGE, SEARCH, DATE, TIME, etc,. Most of the modern browsers have implemented them and are ready to be used in a HTML document. Another exciting feature introduced in HTML5 is the form validation. Instead of writing JavaScript to validate users input, browsers can now validate it and show an appropriate message if the validation fails. The validation message is shown in line with the field for which the validation has failed. The default error message is shown when the validation fails. In this post I'll explain how these error messages can be changed.

Adding beforeRender and afterRender functions to a Backbone View

I was working on a Backbone application that updated the DOM when a response was received from the server. In a Backbone View, the initialize method would perform some operations and then call the render method to update the view. This worked fine, however there was scenario where in I wanted to perform some tasks before and after rendering the view. This can be considered as firing an event before and after the function had completed its execution. I found a very simple way to do this with Underscore's wrap method.

A cheat sheet of keyboard shortcuts in ColdFusion Builder

In my last post I have explained about keyboard shortcuts in ColdFusion Builder 2.0. This blog post contains a list of all shortcut keys and I have listed these keyboard shortcuts based on the categories that it falls into. Well, this post was not planned since users can easily get to know the keyboard shortcuts by navigating to the preferences (ColdFusion -> Profiles -> Keys). However, I met Joshua at Scotch on the rocks in Edinburgh and he suggested that it would be nice to have the list of keyboard shortcuts handy. So this post is for those who would like to have the list with them and refer it whenever required.


Keyboard shortcuts for inserting text:

These are the keyboard shortcuts which are used to insert some text into the editor:

CommandKeyboard shortcuts on WindowsKeyboard shortcuts on MacInsert anchor tagCTRL + T, LCMD + T, LInsert bold tagCTRL + T, BCMD + T, BInsert br tagCTRL + T, RCMD + T, RInsert cfabortCTRL + T, ACMD + T, AInsert cfdumpCTRL + T, DCMD + T, DInsert cfs…