Background

I’ve hosted my blog on a lot of different platforms over the years, Wordpress, Ghost (self hosted and cloud), Jekyll via GitHub Pages, and probably some I’m forgetting. The paid solutions like Wordpress and Ghost were nice and simple, but being a developer I like to maintain and tweak things, and eventually the cost also became an issue for my low-traffic personal blog. When I discovered GitHub pages a few years ago, it seems like the perfect solution for me. Low maintenance, simple, and best of all, free! I decided to go with Jekyll for some reason, and initial setup, choosing a theme, etc.. was easy enough.

Then came the problem.. I don’t update my blog particularly often, sometimes leaving it for years at a time. Inevitably, whenever I did want to write something, I first wanted to make sure it was using the latest version of the theme I’d chosen, and Jekyll. This led to many hours of pain, fighting with Ruby versions, and trying to find a configuration which satisfied all components. Then, things got worse… 😬

Recently I tried Cloudflare Pages for another blog, and loved it. I wanted to have this blog published over on Cloudflare, and then eventually move it off of Github Pages and repoint my domain to Cloudflare. This was even more of a headache, and after a few hours of trying I eventually gave up and decided to try something new ✨

Enter Hugo

I’d heard about Hugo years ago, so I did a bit of research and decided to give it a try. I’m much more familiar with Go than Ruby, so it seemed like a good fit, and Cloudflare natively supported it for their Pages service. Also, it seemed like I’d be able to import my Jekyll posts into it with little to no modification. I did a bit of research and decided to use the PaperMod theme, as it suited my needs and my taste.

I followed the official guide on Cloudflare (link below), and referenced a few other online blog posts to confirm the details. It was easy enough to setup, create the repository, configure Cloudflare Pages, and so on. Of course, it didn’t work! The Cloudflare build failed 😪

The Problems

The build failed at first because Cloudflare couldn’t find PaperMod. After a bit of trial and error and recreating the Git submodule for the theme, it worked!

Now it failed on a different error, progress! 🎉 It seemed like PaperMod didn’t support the version of Hugo that Cloudflare was using to build the site. A bit of searching led me to a very helpful blogpost which explained that, by default, Cloudflare uses a very old version of Hugo. I looked up the latest version of Hugo (the same one that I was using locally), set it in the build config, and retried the deployment… Of course, it failed again! But this time with a different error 💡

This time, it had issues building the various parts of the theme, to do with templating. The logs indicated something interesting. Since version 0.146.0 they’d changed how something was interpreted, and it was warning that it had detected matching elements, and that the behaviour may not be as expected. Armed with this information, I adjusted the config to set the version of Hugo to 0.145.0, the latest one before 0.146.0.

In the end, after a few hours of troubleshooting, it worked! 🎉

Summary

What should have been a quick migration ended up taking multiple hours. Once again, the dependency hell that’s ubiquitous to static site generators caught me out. I’m sure that soon enough the team maintaining PaperMod will update it to work correctly with the most recent version of Hugo, but until then, anyone attempting to setup a new blog using Hugo and PaperMod will likely run into this issue. Below I’ve included a summary of the steps I took to create the blog, migrate my old posts, and set it up correctly in Cloudflare.

Instructions

The official instructions from Cloudflare on how to deploy a Hugo site are pretty good, I mostly follow them, supplemented by the excellent post on ryomayama.com, How to Deploy a Hugo (PaperMod) Site to Cloudflare Pages, which covers PaperMod specifically. I’ve added a few of my own comments and caveats.

1. Hugo Setup

Install Hugo:

brew install hugo

Create your new site:

hugo new site <your hugo site> --format yaml

Note: By default Hugo will use the toml format, this is old and annoying to work with, just tell Hugo to use yaml to make your life easier.

Initialise your Git repo:

cd <your hugo site>
git init

Add the PaperMod submodule:

git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod

Set Hugo to use PaperMod, and create a .gitignore file to exclude the public directory. This directory is where Hugo puts the files it generates, and doesn’t need to be committed to the repo.

echo 'theme: ["PaperMod"]' >> hugo.yaml
echo "public/" >> .gitignore

2. Create a test post

Create your first post, so that you can run Hugo locally and make sure everything works

hugo new posts/hello-world.md

Open up hello-world.md and add whatever content you’d like to it. Note, it’ll be generated with draft: true, but for it to show up on your site you’ll need to either delete this line, or change true to false.

3. Run Hugo to make sure it works

Simply run:

hugo server

The command should succeed and run the Hugo development server. If it works it should output a link that you can visit in your browser, something like http://localhost:1313/. Open the link and make sure the site loads, and that you can view your first post. Try the Hugo Troubleshooting page if it doesn’t succeed.

4. Customising your site

Open up hugo.yaml and you’ll see a few things you can edit which are self explanatory, such as baseURL and title. Update these as you see fit.

There are many more useful options you can include in this file, some examples below. Many of these can be included in your post specific options to override a certain one if you need.

params:
  keywords: [Blog, Tech] # Specify keywords for your blog, for SEO
  author: Yestin # Set the default author of your posts
  defaultTheme: dark # Set the default theme colour
  ShowReadingTime: true # Show the reading time on posts
  ShowShareButtons: true # Show share buttons on posts
  ShowPostNavLinks: true # Show nav links on posts
  ShowBreadCrumbs: true # Show bread crumps on posts
  ShowCodeCopyButtons: true # Show the copy button for code snippets
  ShowWordCount: true # Show the word count on your posts
  showtoc: true # Show the table of contents on your posts
  hideSummary: true # To hide post summary on the home page

  # Display content on your blogs home page, above the list of posts
  homeInfoParams:
    Title: "Hi there"
    Content: Welcome to my awesome blog.
# Define some social icons to show below this content
socialIcons:
    - name: email
      url: 'mailto:[email protected]'
    - name: github
      url: "https://github.com/<your_github_username"

For the full list of the social media icons you can use, see Icons.

# Define a menu to be displayed on the top right
menu:
 main:
 - identifier: home
   name: Home
   url: /
   weight: 10
 - identifier: categories
   name: Categories
   url: /categories/
   weight: 20
 - identifier: tags
   name: Tags
   url: /tags/
   weight: 30

For each post, you can also specify options, one I’ve found useful is:

summary: 'blah'

Which will let you specify the summary of the post, to be displayed under the post’s title on the home page.

For a complete reference see the Hugo documentation or the PaperMod Features/Mods page.

Make sure you re-run hugo server, or if it’s still running, it should auto reload. Check that your blog is as you want it before continuing.

5. Commit your changes and push them to GitHub

Stage all files in your repo and commit them.

git add .
git commit -m "Initial commit"

Push your changes up to GitHub. You’ll have to have a corresponding repo there already.

git remote add origin https://github.com/<your-gh-username>/<repository-name>
git push -u origin main

Check your repo on GitHub to make sure it pushed correctly.

6. Setting up Cloudflare Pages

The final step is to create a new Cloudflage Pages config for your Hugo repo.

Follow the official instructions from Cloudflare here. You can ignore the section on “Base URL configuration”, this didn’t seem necessary.

Most importantly, make sure you DO follow the instructions to use a specific Hugo version. Without this, it won’t work with PaperMod at time of writing.

Cloudflare suggests 0.115.4, however I used 0.145.0, which is more recent and seems to support PaperMod. In future you should probably use the most recent version of Hugo that works with PaperMod. You can visit the Hugo releases page to see if there’s anything more recent. If the version you try doesn’t work, try an older one.

7. Migrate your Old Posts

If you have old posts from Jekyll or another markdown based blogging platform, you can easily import them into Hugo by simply copying them into the correct directory.

For Jekyll, I ran the following command:

cp -r /path/to/jekyll/repo/_posts/ /path/to/hugo/repo/content/posts

They shouldn’t require much modification. I did end up enclosing strings in the options at the top of the posts within single quotation marks. For e.g.

---
title: My blog post title
date: 2022-06-25T10:32:34.000Z
categories: [Sample]
tags: [test]
---

Became:

---
title: 'My blog post title'
date: '2022-06-25T10:32:34.000Z'
categories: ['Sample']
tags: ['test']
---

Conclusion

Thanks for reading, I hope you found this useful and that you have an easier time setting up your new Hugo site than I did 🤞

Acknowledgements

Ryoma’s post, How to Deploy a Hugo (PaperMod) Site to Cloudflare Pages was extremely helpful and in particular mentions specifying the Hugo version in the build config, which I missed at first 🤦‍♂️ It was almost exactly what I needed.