Custom 404 pages in Hugo done right

Learn how to customise your 404 page in Hugo while also avoiding an edge case “soft 404” error.

Ron Erdos • Updated December 28, 2020
Tested with Hugo version 0.80.0

NB: This tutorial is written for people hosting on Netlify. I’m not sure of the specifics when using other hosts.

There are two ways that I know of to generate a custom 404 page in Hugo.

One is easier to implement, but triggers what’s called a “soft 404” error on Google.

The second way (which I recommend) requires a little more setup, but avoids causing a “soft 404” error with Google.

Alternatively, you can download my MoonBooth SEO Theme for Hugo (see bottom of this page) and have everything on this page done for you (assuming you’re using Netlify).

The easy but error-generating option

In this option, we have a template just for the 404 page. It would be called 404.html and live in the root of your /layouts/ folder.

When your site is generated, this would create a page called 404.html in the root of your site.

Some web hosts (such as Netlify) will see this 404.html page and automatically display it, along with the requisite 404 status code, when a page can’t be found. So far, so good. Some themes will even include this for you.

However, the downside of this approach is that the 404 template (which lives at a url of the form example.com/404/) does not itself return a status code of 404—its code is 200. This triggers a “soft 404” error with Google (see box above).

And we really shouldn’t allow our 404 page to return a status code of 200. Now, if you’re thinking that Google won’t find your 404 page, trust me, it probably will, even if you don’t link to it. I’ve seen it happen many times, and each time you will trigger an error with Google. The second option for a custom 404 page in Hugo (below) avoids this problem.

The harder but error-free option

This option requires more work initially, but avoids triggering a soft 404 error with Google.

Here’s how to set it up:

Step 1

If it exists, delete the 404.html template in your /layouts/ folder. We won’t need it, as we’ll be using a custom page instead.

Step 2

Create a new page named 404.md in the root of your /content/ folder. This will become our new 404 page.

Here’s an example of what you could put inside this page:

---
title: Whoops! Page not found
noindex: true
layout: page
---

That page can't be found.

Our latest content is [on the homepage](/).

Step 3

In this step, when the user or Googlebot requests a url that doesn’t exist, we’re going to have Netlify show the 404.md page we created in Step 2 and also send a 404 code.

If you don’t already have a Netlify config file (netlify.toml) in the root of your Hugo site, create one and include this code:

[[redirects]]
	from = "/*"
	to = "/404/"
	status = 404

Now any time a user or Googlebot requests a page that doesn’t exist, the code above will redirect them to /404/ and correctly return a 404 response status code.

Step 4

We need to add the complementary logic in our <head> section which actually generates the noindex tag when it sees noindex: true in the YAML front matter of a piece of content.

I explain how to do this for yourself here; or you can download the MoonBooth SEO Theme for Hugo (see form below) which sets up your 404 page the right way for you.

I'll also send you useful Hugo web dev tips every now and then.

The planets in our solar system