My Impressions of Hugo as a WordPress Developer
Tags: hugo, wordpress, jamstack
Published: 2019-02-15 00:03:39

---
title: My Impressions of Hugo as a WordPress Developer
published: true
description: My impression of Hugo after rebuilding my freelance web development business's site using the Go-based static site generator.
tags: Hugo, WordPress, JAMstack
---

I became a freelance web developer two years ago, and after getting a few clients I built a site for my [freelance WordPress development business](https://deadhandmedia.com). I get most of my business from referrals, so I only spent a few hours building the one-page site as a single HTML file with CSS inlined in the `<head>` tag. 

In the time since I built my business site, I've completed dozens of projects. I wanted to expand my site to show them off, but I could never find the motivation to migrate it to WordPress. I was dreading all of the tiny steps:

1. Setting up a local WordPress environment.
2. Installing all of my go-to WordPress plugins and adding my licenses.
3. Setting up the plugin boilerplate and ACF fields for custom content types.
4. Building a custom theme that matched my brand for all the WordPress templates.
5. Auditing all the WordPress settings.
6. Configuring Yoast SEO to `noindex` all the low-value auto-generated WordPress pages (categories and tags, etc).
7. FTPing everything to the server (I'm using cheap shared hosting).
8. Bouncing the database to the server.
9. Updating the `wp-config.php` file info to point to the new database.
10. Replacing the local URL with the production URL across all tables in the database.
11. Re-entering my plugin licenses.
11. Manually checking the live site to make sure nothing broke.

WordPress is an incredible platform that has paid most of my bills for the past two years. However, its configuration is tedious and I don't feel inspired to go through all the trouble for a site that might get 5 hits on a good day.

I wanted my site to have the following:

* A home page
* An about page
* A portfolio list page and single portfolio item page 
* A contact page


## Hugo and Static Site Generators

I had been hearing about **static site generators** for over a year, so I decided I'd give one a try. 

**Static site generators** use template and content files to generate static HTML pages for an entire site. Sites build with these generators load super fast because there is no backend data processing when you hit the server, and they're super secure because theses sites have no backend. 

After comparing several static site generators, I picked [Hugo](https://gohugo.io/), and by the next day I had deployed a humble 3-page Hugo site to [Netlify](https://www.netlify.com/) (a hosting service that specializes in static sites). 

Even with Hugo and Netlify's learning curve, the site took about the same amount of time it would have taken to build with WordPress. Importantly, I got to skip all 12 WordPress steps I listed above.

Here are my thoughts on Hugo as a WordPress developer.

## Hugo's Separation of Concerns Feels Good

This probably sounds weird, but a lot of times when working in WordPress, the separation of concerns feels *awfully* separated.

* **Sublime Text** for editing code.
* **Terminal** for compiling Scss.
* **MAMP PRO** for running the server.
* **WordPress** for editing content, managing the media library, editing nav menus, defining fields in ACF, and editing site configuration.
* **Sequel Pro** for managing the database.

That's an awful lot of separate tools to manage the same project. 

With Hugo, you can use a much smaller toolset:

* **Sublime Text** for editing code, editing content, managing media, editing nav menus, defining fields, and editing site configuration.
* **Terminal** for running the server and compiling Scss using the `hugo server` command. Terminal is also used for creating new pages.

I love having less things to look at. It helps keep me focused.


## Hugo + Markdown Makes Editing Content Pleasant

Let's start with this: HTML is a verbose language for writing content. WordPress uses a WYSIWYG editor to try to mitigate HTML's verbosity. The WordPress editor can sometimes do wonky stuff, and oftentimes unwanted HTML comes along for the ride when you copy-and-paste from another source.

Markdown fixes that. Without going into too much detail, here's what markdown looks like:

```
# Heading 1
## Heading 2

This is a paragraph.

* This is an unordered list.
* Isn't it cool?

1. This is an ordered list.
2. This is the second item in an unordered list.

[this is a link](https://www.example.com)
![this is an image, and inside these brackets is the alt text](https://www.example.com/img.gif)
```

Because it is plain text, you can copy-and-paste markdown between Google Docs and your text editor with confidence: markdown will render correctly.

*If you want to learn more about markdown, check out this [markdown cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).*

## Hugo Makes URL Structure and Media Management Painless

With Hugo, you create your page structure in the `/content/` folder, so if you had `/content/team.md`, it would show up on your site as `www.example.com/team/`. This is way easier than wrestling with the [WordPress Rewrite API](https://codex.wordpress.org/Rewrite_API).


You could also store the same page at `/content/team/index.md`. This creates something called a **page bundle** in the `/content/team/` folder, which allows you to keep all the assets for the page in the same directory. You could create `/content/team/person1.png` then call the image in the markdown by typing `![Person 1's Face](person1.png)`. 

Compare this to the WordPress media library: WordPress essentially treats every file you have like it's in one big folder, making assets incredibly difficult to find on large sites.

## Hugo's Templating System is Easy to Understand

As a WordPress developer, I have the [WordPress Template Hierarchy Chart](https://wphierarchy.com/) set as the background on my computer because it's complicated and difficult to memorize.

Hugo's templating system is much easier to understand, and it only has a few kinds of commonly-used templates. Here's the rundown of Hugo's templates to the best of my understanding:

* List template (list.html)
* Single template (single.html)
* Homepage (index.html)
* 404 (404.html)

List templates are pages that list other pages (think `www.example.com/blog/`). Single templates display a single resource (`www.example.com/blog/my-blog-post/`). Homepage and 404 templates are self-explanatory.

When you create a theme for Hugo (by the way: Hugo has themes, much like WordPress), you have a `/layouts/defaults/` folder in your theme for templates that *all content* will use by default. For example, `/layouts/defaults/single.html` will be used for all pages that display a single resource (an individual blog page, individual team member page, individual portfolio item page, etc).

However, let's say you have a "services" content type (`/content/services/`) and you want the single page to use a different template. You can create `/layouts/services/single.html` and it will override the default template. I find the Hugo template hierarchy much easier to understand than WordPress.

Hugo uses a wrapper file called `baseof.html`, where you can add markup for  headers and footers so you don't have to manually include them in every template the way you would in WordPress. You can also have a different `baseof.html` for your different content types by using the appropriate folder structure (`/layouts/services/baseof.html`). And like other templating languages, Hugo also allows you to include partials.

Hugo doesn't allow multi-level inheritance the way that Laravel Blade or Twig does, but Hugo is still plenty powerful.

## Hugo Makes Defining Custom Fields Easy

As a WordPress developer, the Advanced Custom Fields plugin is my best friend, but it forces me to spend a lot of time in the browser clicking through its options.

At the top of every markdown file you create in Hugo is a block called **front matter**, and it's used to specify meta-data about the post. 

By default, front matter in Hugo looks like this:

```
---
title: "Blog writing is fun!"
date: 2019-02-13T21:01:46-08:00
---
```

Let's say I wanted to add a custom field to this post. I can literally just add it on the next line.


```
---
title: "Blog writing is fun!"
date: 2019-02-13T21:01:46-08:00
newField: "HELLO WORLD!"
---
```

It's *actually* that easy. 

Now, you probably want to make sure that every content type has the same set of fields. You can do that using **archetypes**. An **archetype** is a predefined set of front matter that populates when you run the `hugo new content/path/to/file.md` in terminal to create a new page.

If I wanted to add custom front matter for an author in my `blog` content type (in my `/content/blog/` folder), I'd create a new file called `/archetypes/blog.md` that had the following:

```
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
author: "Tyler Smith"
draft: true
---

```

With this, every time I create a new blog post from the terminal it will populate with the new fields.

The down side to this YAML-based front matter approach is you don't get the data validation that ACF gives you.

## Hugo Has Lots of Cool Features

In addition to what I've already spelled out, I want to mention a few other features:

* Hugo's server automatically refreshes when you save your project, meaning what's in your browser reflects your project's current state accurately.
* Hugo can run your Sass tasks and will automatically refresh the page on save.
* Hugo can automatically generate scaled images on the fly, and only generates them for the sizes your site uses.
* Support for taxonomies is baked into Hugo 😲
* Hugo has [hundreds of free third-party themes](https://themes.gohugo.io/) available. 
* You can override theme files from third-party themes, much like child themes allow you to do in WordPress.
* A sitemap.xml file is generated by Hugo automatically at build time.
* If you use [Netlify](https://www.netlify.com/) for hosting, you can have your site rebuilt and deployed automatically as soon as you push to the remote of your master Git branch. This means you can always keep your local and production environment synced. 

Getting my site up with Hugo was a great experience, but it wasn't quite painless. Here are the challenges I ran into:

## Go Templating Feels Very Foreign to Me

Hugo uses Go templating from the [Go programming language](https://golang.org/). Go was [invented by giga-nerds at Google](https://golang.org/doc/faq) who were trying to make a faster programming language. You can see their work paid off when you use Hugo: even huge sites can compile almost instantly.

That being said, Go templates just feel really strange to me.

In almost every language I've used, evaluating an expression looks something like `if ($a == $b)`. In Hugo, the same thing would be `if eq $a $b`.

Especially when testing multiple expressions, this can start to look weird. Here's an expression from my site's header file:

```
{{ if or (and (not .Draft) (not (.Param "hidden"))) (.Site.IsServer) }}
    Do stuff...
{{ end }}
```

The double curly braces just indicate that Go template code is being run. 

Also, every logic block ends with `end`.

Assignment looks weird too! Look at this: `$a := 22`.

I'm sure there are good reasons for this odd syntax, and it's not necessarily bad: these are just my impressions of Go templating as a WordPress developer.


## Hugo Has Less Resources Than WordPress When You Get Stuck

Hugo has great documentation, but it doesn't cover everything. There's a lot of Go templating that's used in the docs that isn't thoroughly explained. This is reasonable: it isn't a framework's job to teach you core programming concepts of a language. But if you're coming in totally unfamiliar with Go like I did, you'll need to do some extra work to get up to speed.

Since it's not nearly as widely used as WordPress, Google's search results won't be quite as helpful when you get stuck. Plan to spend some time experimenting as you learn Hugo.

## I Don't Understand Scope or Context In Go


There's a dot (looks like this: `.`) in Hugo that's the keeper of all data and determines you have access to. 

I don't really understand how it works. It's definitely a core concept of Hugo, but I'm still only getting a feel for it.

I found an article that [helped me understand how the dot and scoping in Hugo works](https://regisphilibert.com/blog/2018/02/hugo-the-scope-the-context-and-the-dot/). If you're learning Hugo and the dot confuses you, I'd start your reading here.



## Final Thoughts

I love Hugo and I'll probably keep my freelance web development site on Hugo for years. Being able to do so much inside my text editor is ideal, and because I'm using Netlify's auto-deployment, the content on my local copy is always the same as the content on the production server. The production server is also lightening fast because there's no server-side processing happening to generate the page.

That being said, I don't see myself using Hugo on a client's site: the learning curve that would be required for a client to use Hugo feels too high. Netlify has a CMS that integrates with Hugo, but for most projects I don't feel like the cost/benefit makes sense.

If you're a WordPress developer, it may be worth considering moving your personal site or blog to Hugo for the sheer convenience and benefits I outlined in this post. That being said, I don't think you'll jump platforms and become a full time Hugo developer.

There are also PHP-based static site generators available such as [Jigsaw](https://jigsaw.tighten.co/) by [Tighten](https://tighten.co/). If you're a WordPress/PHP developer, it may be worth checking out Jigsaw to skip the Hugo learning curve and take advantage of Blade templating.

If you want to learn Hugo, I recommend watching [Giraffe Academy's Hugo YouTube Course](https://www.youtube.com/watch?v=qtIqKaDlqXo&list=PLLAZ4kZ9dFpOnyRlyS-liKL5ReHDcj4G3).