TL;DR
- https://gohugo.io/content-management/urls/
- there are several ways to control routing
- default: file path within the content directory
- front matter slug overwrites last segment of path
- front matter url overwrites the whole path
- permalink settings
- front matter url overwrites any matching permalink pattern
My configuration
Above screenshot shows the structure of the code that powers this blog. I chose to have a directory
structure that fits my way of organizing/thinking. In consequence, I also chose to use the url in the frontmatter to
control the full routes explicitly per article.
The article in content/post/hello-world/index.md
has url = 'hello-world/'
in the front matter so
the post will be available under “https://miriam-mueller.com/hello-world". Within the rules Hugo applies,
you are free to do what suits you best. You could achieve the same result with this structure: content/hello-world.md
,
for example. The benefit I saw in my structure is, that I can place all assets used in the post in one folder with its
markdown.
Migrate WordPress routes
Firstly, you need to know the routes you have. This sounds more simple than it is, because WordPress generates a lot of stuff you might not even know about. How to find out your routes? You can generate an export of your WordPress site in xml format and look them up. I had my site indexed at Google and with a Google Search Console account you can quickly access your “most important sites” from the point of view if they were frequently accessed because of being a search result and ranking well.
Decide what to keep
Migrating the articles is quite simple. My scheme was baseURL/article-title/
and I decided to keep the routes as they were
for already published articles. For asset-URLs (images) I chose to not include the old routes in my nginx-configuration. The same
accounts for css/js of my WordPress theme. This means, if - for example - someone bookmarked the asset URL, they will now
end up in my new blog with the default 404 page.
For routes that you want to redirect into your new blog, you need to setup nginx rewrite rules. In my case, this accounted for the Marp Cheatsheet and routes for categories and tags because I wildly used them in my old blog. If you - like me - decide to use the opportunity to cleanup, you will end up with a lot of redirects, but it is worth the effort.
Exemplary nginx redirects
location = /wp-content/uploads/2024/05/MarpCheatsheet.pdf {
return 301 /MarpCheatsheet.pdf;
}
location ~* ^/2024/?$ {
return 301 "/archives/#2024";
}
location ~* ^/category/symfony/?$ {
return 301 /tags/symfony/;
}
Hugo taxnonomy configuration
In order for the tags-routes and archive pages to work, you need to configure the
taxonomies in the config.toml
:
[taxonomies]
year = 'year'
tags = 'tags'
For the archive page to work you have to define the year in the front-matter of each article, as well as the date. The rest will be generated automatically by Hugo.
+++
date = '2025-03-15T17:00:00+01:00'
draft = false
title = 'Hugo directory structure & routing'
tags = ['hugo', 'wordpress']
year = 2025
url = 'hugo-directory-structure-and-routing/'
+++
If you want to influence a tag page, you can add content/tags/<insertTag>/_index.md
. For example in the front-matter
you can set a page title and description. The /tags
route will be automatically
generated by hugo once you use tags.