For people migrating existing published content to Hugo, there’s a good chance you need a mechanism to handle redirecting old URLs.

Luckily, redirects can be handled easily with aliases in Hugo.

Example

Given a post on your current Hugo site, with a path of:

content/posts/my-awesome-blog-post.md

… you create an “aliases” section in the frontmatter of your post, and add previous paths to that.

TOML frontmatter

+++
...
aliases = [
"/posts/my-original-url/",
"/2010/01/01/even-earlier-url.html"
]
...
+++


YAML frontmatter

---
...
aliases:
- /posts/my-original-url/
- /2010/01/01/even-earlier-url.html
...
---


Now when you visit any of the locations specified in aliases, assuming the same site domain, you’ll be redirected to the page they are specified on.

Important Behaviors

1. Hugo makes no assumptions about aliases. They also don’t change based on your UglyURLs setting. You need to provide absolute path to your webroot and the complete filename or directory.

2. Aliases are rendered prior to any content and will be overwritten by any content with the same location.

Multilingual example

On multilingual sites, each translation of a post can have unique aliases. To use the same alias across multiple languages, prefix it with the language code.

In /posts/my-new-post.es.md:

---
aliases:
- /es/posts/my-original-post/
---


How Hugo Aliases Work

When aliases are specified, Hugo creates a physical folder structure to match the alias entry, and, an html file specifying the canonical URL for the page, and a redirect target.

Assuming a baseURL of mysite.tld, the contents of the html file will look something like:

<!DOCTYPE html>
<html>
<title>http://mysite.tld/posts/my-original-url</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta http-equiv="refresh" content="0; url=http://mysite.tld/posts/my-original-url"/>

The http-equiv="refresh" line is what performs the redirect, in 0 seconds in this case.