The Subfolder Problem#

For anyone who’s tried hosting a website from the subfolder, e.g., https://www.example.com/blog, you know that this can often lead to issues like broken links or incorrectly styled elements. This is due to many frameworks assuming you are hosting out of the root of the web site. While Hugo has a way to configure a site for this, there are some things you may need to adjust in order to make it work.

The Basics#

To set up a site that is hosted out of a subfolder, you first need to set the baseURL in the site’s .toml file to indicate the subfolder name

baseURL = "https://www.example.com/blog"

In the example above, the www.example.com doesn’t have to be the actual site’s domain, it can be any domain value. The important part to is to indicate the subfolder, blog in the setting. If you start up the dev server you’ll see that the pages are correctly hosted at http://localhost:1313/blog . Everything seems great until you look at a page with an image on it. Unless you explicitly account for the subfolder in your source markdown files (those in the content folder), they will likely be broken.

The brute force solution is to go through each .md content file and add in the subfolder name.

[Alt Text]("/blog/images/image_name.png")

The Flexible Solution#

A more flexible solution is to take advantage of Hugo’s shortcode feature. These are reusable snippets of HTML template code that you can place in your .md files. To create a custom shortcode, make a shortcodes folder under layouts and add an image.html file. Here are the contents:

<img src='{{relURL "images"}}/{{ .Get "src" }}' alt='{{ .Get "alt" }}' />

Let’s break this down:

img - as you would expect, this creates an img HTML element

{relURL "images"} - uses the built in relURL command to get the relative URL of the “images” folder. For a site with the baseURL set to https://www.example.com, this will return /images. For a site with the baseURL set to https://www.example.com/blog, this will return /blog/images.

/ - path / file name separator

{{ .Get "src" }} - Gets the src attribute set in the .md file. This will become clear in the next section.

{{ .Get "alt" }} - Gets the alt attribute set in the .md file.

Using the Custom Shortcode#

In order to use the custom shortcode, you would replace the normal image definition:

[Alt Text]("/blog/images/image_name.png")

with this:

{{<image src='image_name.png' alt='Alt Text'>}}

The tag name, image, is whatever you named the file in the layout/shortcodes folder. When Hugo generates the HTML for the content file, it will correctly set the src attribute of the img tag to include the subfolder name.

Conclusion#

Setting things up this way gives you flexibility in the future in case you ever need to move the site to a different subfolder path. If you need to do that, all you would need to do is change the baseURL value in the site’s .toml file and run the Hugo command to regenerate the site. All of the image tags will be generated correctly using the new subfolder name.