Migrating to Hugo

I started this site back in 2013 as a place where I could share my ideas, projects, and things I find interesting. At the time, the personal blog space seemed to be dominated by Wordpress. It was the clear winner for me to get my first site up and running. There were many tutorials and themes available for standing up a new site, which was especially helpful for people with minimal web experience like myself. I also went with Hostgator as a hosting provider since they have decent Wordpress integration out of the box. The Wordpress/Hostgator combination has served me well over the years. It was the right decision, for me, when I first started this journey. However, over the years I began to realize that this combination was not really meeting my needs and expectations. I felt like my site could be much better in many ways, especially taking into account how I have been using it so far.

Deciding to re-write

After feeling dissatisfied with the state of my site I made the decision that I would need to just scrap it and re-write from scratch. I didn’t really want to put more effort into learning Wordpress or PHP. I’m not much of a web developer, and running a LAMP stack seemed like total overkill for how I’ve been using my site. I also didn’t like the amount of spam that came through my contact form as well as post comments, even though I had been running blockers for that sort of thing.

The site ended up feeling like a security hole. I just don’t want to have to worry about maintaining a server to run a simple blog. I knew that I wanted/needed to drastically simplify my overall site design and infrastructure.

Enter Hugo

After making the decision to re-write, it was clear to me early on that I would use a static site generator for the new site. I like the simplicity of just working with text files for posts. I wouldn’t need to support any complex infrastructure, and it would make local development a breeze.

Hugo, Pelican, and Zola were the first few generators that I looked into. After doing some high level research I quickly ruled out Pelican and Zola. Pelican is mature but seemed to be lacking in the speed department. I was interested in Zola since its fast and written in Rust, but it didn’t have the same level of documentation and user base that Hugo does. Ultimately, Hugo’s speed, documentation, and community made it the easy choice for me.

The re-write

I started the re-write by going through some basic getting started tutorials. I tried a few different iterations of creating a starter site just to get a feel for the framework. I even thought about writing the site from scratch (no themes). This seemed like a little more work than I wanted to sign up for.

In the end I decided to use a similar technique that I had when I originally started the site, which was to find a theme that came close to what I was looking for, and customize from there. I ended up settling on the Hermit theme as a base for my site.

After having my base lined up I was able to start customizing various template/html/css/md files.

Parts of the process went smoothly while other things took a little longer than expected. I think it would have saved me some headaches if I had just read up on go templates before diving into working with them through Hugo’s framework. I eventually needed to read up on the go template engine to fully understand some of the syntax and functionality that Hugo provides.

One of the early hurdles was figuring out how to correctly use Hugo’s image processing capabilities. With Wordpress, I was able to just upload images and it took care of resizing and serving the right image file based on screen size. Since I want my site to be fast, I knew this was something I’d like to accomplish with Hugo. Luckily, Hugo can do this sort of thing out of the box. It resizes images at build time through a custom img.html shortcode I wrote, that makes use of img and srcset to point various screen sizes to the correct image resolution. Here is the shortcode I’m currently using for image processing:

{{/* Get image by its name local to the page bundle */}}
{{ $src := .Page.Resources.GetMatch (.Get "src") }}

{{/* Resize the src image */}}
{{ $tiny := ($src.Resize "500x") }}
{{ $small := ($src.Resize "800x") }}
{{ $medium := ($src.Resize "1200x") }}
{{ $large := ($src.Resize "1500x") }}

{{/*
    Here we only use images smaller than or equal to the src (original) image
    size, since Hugo will upscale small images. We also set the sizes attribute
    to (min-width: 35em) 1200px, 100vw unless overridden in shortcode
*/}}

<img 
  sizes={{ default "(min-width: 35em) 1200px, 100vw" (.Get "sizes") }}
  srcset='
  {{ if ge $src.Width "500" }}
    {{ with $tiny.RelPermalink }}{{.}} 500w{{ end }}
  {{ end }}
  {{ if ge $src.Width "800" }}
    {{ with $small.RelPermalink }}, {{.}} 800w{{ end }}
  {{ end }}
  {{ if ge $src.Width "1200" }}
    {{ with $medium.RelPermalink }}, {{.}} 1200w{{ end }}
  {{ end }}
  {{ if ge $src.Width "1500" }}
    {{ with $large.RelPermalink }}, {{.}} 1500w {{ end }}
  {{ end }}'

  {{/* Default to medium src otherwise use the original */}}
  {{ if .Get $medium }}
    src="{{ $medium.RelPermalink }}"
  {{ else }}
    src="{{ $src.RelPermalink }}" 
  {{ end }}
  {{ with .Get "alt" }}alt='{{.}}'{{ end }}
  {{ with .Get "width" }}width='{{.}}'{{ end }}
  {{ with .Get "height" }}height='{{.}}'{{ end }}>

I followed a few example posts here and here which were really helpful for working out the kinks. I found the documentation to be a little confusing on this front, so it was nice to see how other people made this work on their sites.

Working through the image processing also pushed me in the direction of using page bundles for all of my posts. I originally started creating each post as a single markdown file using static assests for any images within the post. However, the dynamic sizing/loading of images doesn’t work for static resources. I also think page bundles are a slightly cleaner. All of the resources can live in the same folder as your post, which makes organization a little easier.

Getting the site to be fully reactive was another goal of mine for the re-write. This part of the development didn’t have much to do with Hugo itself but Hugo certainly helped. I mostly needed to keep making css tweaks until the site was behaving the way I wanted it to. Hugo’s live reload was great for this, allowing me make small changes and see those changes take effect immediately. Hugo also supports scss which makes working with css slightly less awful.

Hosting

Switching hosting providers was something I knew I wanted to do along with the re-write. Having a statically generated site provides a lot of options here. I could have hosted my own site with a linux vm (ec2, linode, digital ocean, …), use a storage service like S3, or go with a specialized static site hosting provider (github, netlify).

One of the main goals for switching hosting was to make deployments as push button as possible. Also I knew I was paying way more for hosting than I needed, so the new hosting solution had to be cheaper than what I was currently paying.

I ended up settling on Netlify which has been working great so far. They were the cheapest option (free) and seemed to have some really great features (including solid Hugo integration), so I figured I’d give them a try. If it doesn’t work out I can always evaluate other options if needed. I took a look at hosting with Github since they’re hosting my code, however, I quickly realized Netlify provides better integration for Hugo based static sites.

Netlify supports a really nice PR system for deploying the site. I have hooked their deployment system up to my Github repository, which can be set up in a few minutes. I currently maintain a develop, and a master branch for this site. The develop branch is for new posts or site changes that I am working on, and master is for what gets deployed to production. I set it up so that when I create a PR against master Netlify deploys a preview of the site to their platform. Once I have verified it looks the way I think it should, I can just merge to master, and they take care of the rest of the production deployment. It doesn’t get much more push button than that.

They’re also quite fast and provide a caching layer that serves the site quickly. I was able to use https out of the box and they handle custom 404.html files automatically.

Netlify provides some interesting payed features if you are looking to get more functionality out of your static site. I don’t see myself making use of those features anytime soon, but it’s nice to know that functionality is available.

So far I am really happy with Netlify. Took almost no time to get up and running, and maintenance should be quite simple going forward. Another benefit of a static site is that I can always easily switch hosting if my requirements change.

Next steps/plans for the future

My hope is all the changes that I have made take a lot of the friction out of maintaining the site, and will allow me to post more frequently. I have a few ideas for upcoming posts so be on the look out for those.

I’m currently still using Hostgator for domain name registration, so I’d like to look into other options there as well.

I’m really liking how the site turned out and am pretty happy with it’s current state. However, there’s still a lot of room for improvements, both visually and functionally, so it’ll be great to keep evolving the site. Making changes should be much more simple now that I no longer need to worry about databases or servers. Overall, I’m super excited to keep this thing going, and I’m looking forward to building and sharing new things on this platform.