Setting up a website with the Hugo framework



In this post we are going to set up and deploy a new Hugo website to replace my old Wordpress installation.

The reasoning behind switching to hugo

Ever since the creation of my first website, i have mostly been using Wordpress running on a classic LAMP-stack to host my personal websites and projects.

However i have grown tired of looking after my wordpress-blog (for reasons we get into further down in this article) and decided to switch to Hugo

What is hugo?

Hugo describes itself as “The world’s fastest framework for building websites”.
Here are some facts about Hugo:

If you have no prior experience with static website generators, consider reading this article explaining the concept, and maybe take a look at the principles of the JAM-stack as well.

Why i decided to switch to Hugo

Here are the three main reasons i decided to switch to using Hugo as my blogging platform:

WordPress is overpowered and bloated (for my personal use)

While WordPress is often viewed as the de-facto platform for blogging and personal websites. Something people often fail to mention though, is that WordPress is also a Content Management System.
CMS are a powerful and versatile way to implement almost any kind of websites. Sounds good, but the downside is that they come with myriad of stuff that is completely unnecessary for hosting a simple small website. User management, dashboards, plugins, and a need for a database are just some examples of functionalities that are a total overkill for small, personal websites, such as this blog.

Using CMS also has certain security implications: WordPress is used to run approximately 35% of all currently existing websites, so it's a great target for hackers to try and exploit.

A good article providing more insight on this subject can be read here.

Content input

This is more of a personal preference of mine, but i greatly dislike using the Wordpress editor. Is it powerful and highly modular? Sure. Would i even go as far as to call it an objectively good piece of software? Yes. The problems that i have with the editor are as follows: i don't want to log into the dashboard and be forced to use an UI for writing a quick blog-post, and i like writing my stuff in markdown.

Hugo (in accordance to JAM-stack's principles) consumes markup by default, so i can focus on writing messing around in the Wordpress editor.

Deployment and version control

Because Hugo deploys static websites, all of the website's code can be stored in git, and
the lack of a database means that deployment can be performed with 2 commands:

$ git pull
$ hugo -d /path/to/webroot/

Additionally if you don't have a server to run your website on, Hugo's static nature allows deployment and hosting on a number of different platforms, such as AWS S3, Github pages, Bitbucket and many more.



Install Hugo and initialize a new site

Note:
A complete list of all installation methods for every supported OS can be found here.

I am going to host my Hugo website in a virtual server. Even if you plan to use some other method of hosting your site, you can still read along until we get to the part about deploying.

Start by installing Hugo.
There are many different methods to do this, but i went with brew:

$ brew install hugo

Verify installation:

hugo version

Create a folder for your Hugo project and initialize a new site called personal-blog:

$ mkdir website && cd website
$ hugo new site personal-blog

Congratulations! Your new Hugo site is created in /path/to/project/personal-blog.

Just a few more steps and you're ready to go:

1. Download a theme into the same-named folder.
   Choose a theme from https://themes.gohugo.io/ or
   create your own with the "hugo new theme <THEMENAME>" command.
2. Perhaps you want to add some content. You can add single files
   with "hugo new <SECTIONNAME>/<FILENAME>.<FORMAT>".
3. Start the built-in live server via "hugo server".

Visit https://gohugo.io/ for quickstart guide and full documentation.

We now have a folder called personal-blog that houses the code for the website.
A comprehensive explanation of the folder structure can be found here.



Install a theme and create a blog post

Before adding content to our site, let's first add a theme to it.

Hugo has a robust built in theming engine, but i encourage you to start by picking one of the hundreds of pre-made themes found here.

Installing and swapping between themes in Hugo is very simple: Just clone or unzip them to the themes/ folder located in the project's root directory.

I chose a theme called Manis:

// Clone theme from source
$ cd themes/
$ git clone https://github.com/yursan9/manis-hugo-theme.git

Cloning into 'manis-hugo-theme'...
remote: Enumerating objects: 55, done.
remote: Counting objects: 100% (55/55), done.
remote: Compressing objects: 100% (40/40), done.
remote: Total 1064 (delta 18), reused 35 (delta 11), pack-reused 1009
Receiving objects: 100% (1064/1064), 1.43 MiB | 2.83 MiB/s, done.
Resolving deltas: 100% (522/522), done.

// or download and uzip
$ cd /path/to/file
$ unzip manis-hugo-theme-master.zip -d /path/to/project/themes/

To activate the theme, we need to add it's name to configuration.toml.
The name of the theme should match whatever your theme folder is called:

$ mv themes/manis-hugo-theme-master themes/manis
$ echo 'theme = "manis"' >> configuration.toml

That's all we need to do to get up and running with a new theme.

Start local developement server

At this point it's a good idea to start a local Hugo development server to see your website in action:

$ hugo server -D

                   | EN  
+------------------+----+
  Pages            |  7  
  Paginator pages  |  0  
  Non-page files   |  0  
  Static files     |  7  
  Processed images |  0  
  Aliases          |  0  
  Sitemaps         |  1  
  Cleaned          |  0  

Built in 4 ms
Watching for changes in /path/to/project/personal-blog/{archetypes,content,data,layouts,static,themes}
Watching for config changes in /path/to/project/personal-blog/config.toml
Environment: "development"
Serving pages from memory
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop

Open a browser and go head over to localhost:1313 to see your website in action:

Picture from localhost:1313

Hugo development server will watch your project folder, and rebuild the site whenever it detects changes. In practise this means that as long as you keep the server running, you can see the changes you make to your site in real time.



Add content

Now that we have a functional website running in our localhost, lets add some content to the site.

Navigate to your project's root directory, and run the following commands to create a folder for your blog posts as well as a new post itself:

$ mkdir content/blog
$ hugo new page content/posts/first-post.md
/path/to/project/personal-blog/content/posts/first-post.md created

This will create a new file called first-post.md that will look something like this:

---
title: "My First Post"
date: 2019-03-26T08:47:11+01:00
draft: true
---

The text contained in within the --- lines are called front matter, and contain data such as meta-tags, a summary, slug, etc.
All you have to know for now though, is that when you are done writing your post, you need to change the draft value to false in order for Hugo to compile it.

You might notice we don't see out newly created post on the page yet.

Because some funtionality and features can differ from theme to theme, you shoulds start by copying a sample configuration to your site's config.toml located in the project's root folder.

This example configuration can usually be found and copied from /themes/your-theme/exampleSite/config.toml

Now find a [menu] block from your configuration file. Here's an example from my configuration file:

[menu]
        [[menu.main]]
                name = "Post"
                url = "/post/"

        [[menu.main]]
                name = "About"
                url = "/about"

As you might already have figured out, each file and folder starting from /content corresponds to their respective URL paths. Here's some examples:

www.example.com/about/            -->  content/about.md
www.example.com/posts/blog-post/  -->  content/posts/blog-post.md
www.example.com/guides/hugo/post/ -->  content/guides/hugo/post.md

Modify the configuration file to match your file structure.
If you've been following along with the mantis theme, this is what the block should look like:

[menu]
	[[menu.main]]
		name = "Posts"
		url = "/posts/"

NOTE:
Don't forget to change the draft value to false when you are done!
Hugo will only build and serve files with the draft value of false.



Create a git workflow

Regardless of the hosting option you are going to use, i highly recommend checking your website's source code to some type of version control.
Usage of a version control system is out of scope for this article, but a good beginner's guide on Git can be found here.

Let's start by initializing a new git project:

$ git init

Some folders might be empty by default, so remember to add .gitkeep files to get them tracked.

Commit files and push them to your repository:

$ git add .
$ git commit -am "Inital commit"
$ git remote add origin <remote repository URL>
$ git push origin master


Deploy the site

NOTE:
I'm deploying my site to a virtual server running Nginx. For other (including some free) hosting options, check out this article.

Deploying a Hugo site to a webserver is extremely simple:

  1. Git clone or otherwise move your website's source to the target server
  2. run hugo in project's root folder. This produces a public folder containing your compiled Hugo website
  3. Point your webserver's documentroot to that public folder.


Summary

Hugo is a great alternative to people who want their website to have as little overhead and bloat as possible. Despite it's small footprint, Hugo provides extremely powerful and versatile systems for templating, theming and configuration management.

But the static nature of Hugo (and the JAM-stack in general) comes with a price: it's only great for mostly static sites that are meant to be consumed as is, such as blogs, portfolios and landings pages.
If your page is going to have a lot of changing content, requires manipulation of the DOM, a need to track states, or some other form of dynamic content, then Hugo obviously isn't the tool for the job.
(For more information, here's a great article detailing when not to use hugo.)

More posts regarding Hugo coming in the near future!



Administrivia

09.03.2020 – Fixed some typos

Sources