Specifying URL Path Segments in Hugo
Updated 2021-October-8

Page contents


2021-September-1  Published this evolving⁠[1] article.



This article assumes…

  • you are using Hugo v0.83.0⁠[2] or newer,

  • you know how to use Hugo bundles,

  • and you are comfortable with zero-⁠based numbering (0,1,2,… rather than 1,2,3,…), which is used in Go slice expressions.


URL paths in Hugo

Default URL paths

By default, a Hugo-generated web page’s URL path closely matches the path of its primary source file. For example, the hugo command transforms this Infinite Ink source file:


to this destination file:


When this destination file is put on the Infinite Ink web server, the URL is:


For more about this, see Infinite Ink’s…


Overriding default URL paths

To override Hugo’s default URL paths, you can…

  • specify Permalinks patterns in a Hugo config file

  • and/or use one or more of these keys in the front matter of a page’s primary source file:

    • url

    • slug

    • aliases

To learn about this, see gohugo.io/content-management/urls/.


Below I give examples of using Permalinks to specify non-⁠default URLs.


This page’s source file, destination file, and URL

This page’s source and destination files

The source file of this page is:


And the destination file is:



This page’s URL and some URL terminology

The URL of this page is:


The scheme is:


The hostname (also known as domain name and authority) is:


The path is:


Each of the following is a path segment:


The last part of this URL path, sections, is sometimes called the slug.


To learn more about URL terminology, see wikipedia.org/wiki/URL.


Learn to specify URL path segments by example

Example 1: Remove articles path segment from this page’s URL

Since I do not want the string articles to be in the URL of this page (or any page in the content/articles/ directory), I do the following three steps.


A. Make all but the last content directory a branch bundle

Here is the part of Infinite Ink’s directory structure that is relevant to this page’s source file.

└── content
    ├── _index.md
    └── articles
        ├── _index.md
        └── hugo-urls
            ├── _index.md
            └── nested
                ├── _index.md
                └── sections
                    └── index.adoc


  • The four directories content, articles, hugo-urls, and nested are each a branch bundle.

  • The three directories articles, hugo-urls, and nested are each a section.

  • articles is sometimes called the root section.

  • The last directory, sections, is a leaf bundle and is not a section.

  • The file extensions .md and .adoc can be any of the content file extensions known to Hugo.

  • The content of each of the four _index.md files can be as simple as this:

# Important: Front matter is required.
# Because of this _index.md file, this directory is a branch bundle.


Infinite Ink’s config.yaml includes this:

  articles: /:sections[1:]/:slug/
                      slice syntax


To use the above slice syntax, you need to be using Hugo v0.83.0⁠[2] or newer.


C. Use the hugo command to build the website

With the above structure and settings, the hugo command generates this destination file:




Example 2: Change products/shirts to p/shirts in Simone’s website

On 2021-August-29, Simone posted about Folder hierarchy in permalink in stackoverflow.com’s Hugo tag. Here is an excerpt of his question:

I want to have URLs like:

  • content/products/shirts/very-beautiful-shirt.md => /p/shirts/very-beautiful-shirt

From what he wrote, it seems his content/ directory includes this:

└── content
    └── products
        ├── shirts
        │   ├── simple.md
        │   └── very-beautiful-shirt.md
        └── hats
            └── simple.md

And he wants the hugo command to generate this in the public/ directory:

└── public
    └── p
        ├── shirts
        │   ├── simple
        │   │   └── index.html
        │   └── very-beautiful-shirt
        │       └── index.html
        └── hats
            └── simple
                └── index.html


Steps A, B, and C below should do this.


A. Use bundles everywhere

To get the URLs that Simone wants, it seems (based on my experiments) that each directory on the path must be a bundle. Here is the structure that works for me:

└── content
    ├── _index.md
    └── products
        ├── _index.md
        ├── shirts
        │   ├── _index.md
        │   ├── simple
        │   │   └── index.md
        │   └── very-beautiful-shirt
        │       └── index.md
        └── hats
            ├── _index.md
            └── simple
                └── index.md


Specify this in a config.yaml:

  products: /p/:sections[1:]/:filename/
                        slice syntax


Or this in a config.toml:

  products = '/p/:sections[1:]/:filename/'
                          slice syntax


C. Use the hugo command to build the website

With the above structure and settings, the hugo command generates the destination files and URLs that Simone wants.


About slices

:sections slice syntax

Sections slice syntax, such as :sections[1:] used above, was introduced in Hugo v0.83.0.⁠[2] Here are some examples that help to explain the meaning of this syntax.

Syntax Zero-⁠Based
Example if sections are





























Thanks to the following for some of the above examples.


  • :sections[0] is sometimes called the root section.

  • :sections (without slice syntax) means “all sections.”


About Go slice expressions

To learn about Go slice expressions, see golang.org/ref/spec#Slice_expressions


See also


1. Many Infinite Ink articles, including this one, are evergreen and regularly updated.
2. Hugo v0.83.0 was released 2021-May-1.⁠💐

Comments 👍 👎 📝

Your public comment might immediately improve this page or help me to (eventually) improve this page.