I used to utilize GitHub Pages to serve static content for my blog. I secured it behind Cloudflare to employ a custom domain and automate HTTPS certificate management. Additionally, I utilized a few Page Rules to implement redirects:
- From www.* to non-www,
- From HTTP to HTTPS,
- And for some SEO renaming.
Unfortunately, in the Free plan from Cloudflare, you are limited to:
- 3 Page Rules (with simple glob matching),
- 10 Transformation Rules (no regex rules),
- 10 Redirect Rules (no regex).
I made use of a combination of these rules, but due to these limitations, I couldn’t meet all of my requirements. I have few hundreds of broken URLs reported by Google Web Console. Google still remembers that I migrated from Wordpress and attempts to index some paths I no longer host. Although I attempted to utilize Hugo’s aliases 1, it only facilitates 1-to-1 matching. I’m unable to address this issue within these constraints.
On the flip side, Cloudflare Page supports the _redirects
file, which can host 2000 static and 100 dynamic redirects, totaling up to 2100 redirects 2. That’s more than what I need.
I decided to transition static file hosting to Cloudflare Pages3. There’s a helpful article describing the configuration , and the process is quite straightforward.
Now, what I needed was an easy way to generate this _redirects
file.
Generating _redirects
within Hugo
Basic syntax of _redirects
files is simple 4:
[source] [destination] [code?]
I’d like to generate it automatically from Hugo’s aliases, then add few more. For that let create a new template file under layouts/_default/home._redirects
with the following content:
{{- range .Site.Pages -}}
{{- if .Aliases -}}
{{- $new := .RelPermalink -}}
{{- range .Page.Aliases }}{{ . }} {{ $new }} 301
{{ end -}}
{{- end -}}
{{- end -}}
At the end of this file, you can add your own custom redirects. For me, these include taxonomy changes:
/tag/* /tags/:splat 301
/category/* /categories/:splat 301
/main/* / 301
/author/* /authors/:splat 301
Now, in the config.yaml
or hugo.yaml
, add the configuration to handle the new file type:
mediaTypes:
text/redirects:
outputFormats:
_redirects:
name: _redirects
mediaType: text/redirects
baseName: _redirects
isPlainText: true
rel: alternate
isHTML: false
noUgly: true
permalinkable: false
outputs:
home:
- HTML
- RSS
- JSON # I need it for the search
- _redirects
That’s it. Deploy/rebuild your website at Cloudflare and check if redirects work as expected.
I must admit it’s not my original idea — I found it in the sources of russ.foo ’s blog. Check it out, there are more fancy modifications.