HUGO
Menu
GitHub 90163 stars Mastodon

Configure permalinks

Configure permalinks.

Use the permalinks configuration to define custom URL patterns for your pages. Hugo supports two forms: a map form for simple section-based patterns, and an array form that supports page matchers for more precise targeting.

The url front matter field overrides any matching permalink pattern.

Map form

Define URL patterns for each top-level section, keyed by page kind. For example, this configuration defines URL patterns for the articles section page and its descendants:

permalinks:
  page:
    articles: /blog/:year/:month/:slug/
  section:
    articles: /blog/
[permalinks]
  [permalinks.page]
    articles = '/blog/:year/:month/:slug/'
  [permalinks.section]
    articles = '/blog/'
{
   "permalinks": {
      "page": {
         "articles": "/blog/:year/:month/:slug/"
      },
      "section": {
         "articles": "/blog/"
      }
   }
}

The supported page kinds are home, page, section, taxonomy, and term.

To configure permalinks per language, nest the permalinks key under the language key:

languages:
  de:
    label: Deutsch
    locale: de-DE
    permalinks:
      page:
        articles: /artikel/:year/:month/:slug/
      section:
        articles: /artikel/
    weight: 1
  en:
    label: English
    locale: en-US
    permalinks:
      page:
        articles: /blog/:year/:month/:slug/
      section:
        articles: /blog/
    weight: 2
[languages]
  [languages.de]
    label = 'Deutsch'
    locale = 'de-DE'
    weight = 1
    [languages.de.permalinks]
      [languages.de.permalinks.page]
        articles = '/artikel/:year/:month/:slug/'
      [languages.de.permalinks.section]
        articles = '/artikel/'
  [languages.en]
    label = 'English'
    locale = 'en-US'
    weight = 2
    [languages.en.permalinks]
      [languages.en.permalinks.page]
        articles = '/blog/:year/:month/:slug/'
      [languages.en.permalinks.section]
        articles = '/blog/'
{
   "languages": {
      "de": {
         "label": "Deutsch",
         "locale": "de-DE",
         "permalinks": {
            "page": {
               "articles": "/artikel/:year/:month/:slug/"
            },
            "section": {
               "articles": "/artikel/"
            }
         },
         "weight": 1
      },
      "en": {
         "label": "English",
         "locale": "en-US",
         "permalinks": {
            "page": {
               "articles": "/blog/:year/:month/:slug/"
            },
            "section": {
               "articles": "/blog/"
            }
         },
         "weight": 2
      }
   }
}

The map form does not support the target key. Use the array form to apply URL patterns with a page matcher.

Array form

New in v0.161.0

Define an array of permalink entries to apply different URL patterns to different subsets of pages. Hugo applies the first matching entry. Each entry supports the following keys:

pattern
(string) The URL pattern, constructed with tokens. Required.
target
(map) A page matcher that limits the URL pattern to a subset of pages. Optional.

For example, this configuration defines URL patterns for the articles section page and its descendants:

permalinks:
- pattern: /blog/
  target:
    path: /articles
- pattern: /blog/:year/:month/:slug/
  target:
    path: /articles/**
[[permalinks]]
  pattern = '/blog/'
  [permalinks.target]
    path = '/articles'
[[permalinks]]
  pattern = '/blog/:year/:month/:slug/'
  [permalinks.target]
    path = '/articles/**'
{
   "permalinks": [
      {
         "pattern": "/blog/",
         "target": {
            "path": "/articles"
         }
      },
      {
         "pattern": "/blog/:year/:month/:slug/",
         "target": {
            "path": "/articles/**"
         }
      }
   ]
}

Target

In the array form, the optional target key accepts a page matcher to limit the URL pattern to a subset of pages. If you omit target, the URL pattern applies to all pages.

A page matcher filters pages by logical path, page kind, environment, or site. Specify filtering criteria using any combination of the following keywords.

environment
(string) A glob pattern matching the build environment. For example: {staging,production}.
kind
(string) A glob pattern matching the page kind. For example: {taxonomy,term}.
lang
Deprecated in v0.153.0
Use the sites setting instead.
path
(string) A glob pattern matching the page’s logical path. For example: {/books,/books/**}.
sites
New in v0.153.0
(map) A sites matrix matching any combination of content dimensions including language, version, and role.

For example, this configuration defines language-specific URL patterns for the articles section page and its descendants:

permalinks:
- pattern: /artikel/
  target:
    path: /articles
    sites:
      matrix:
        languages: de
- pattern: /artikel/:year/:month/:slug/
  target:
    path: /articles/**
    sites:
      matrix:
        languages: de
- pattern: /blog/
  target:
    path: /articles
    sites:
      matrix:
        languages: en
- pattern: /blog/:year/:month/:slug/
  target:
    path: /articles/**
    sites:
      matrix:
        languages: en
[[permalinks]]
  pattern = '/artikel/'
  [permalinks.target]
    path = '/articles'
    [permalinks.target.sites]
      [permalinks.target.sites.matrix]
        languages = 'de'
[[permalinks]]
  pattern = '/artikel/:year/:month/:slug/'
  [permalinks.target]
    path = '/articles/**'
    [permalinks.target.sites]
      [permalinks.target.sites.matrix]
        languages = 'de'
[[permalinks]]
  pattern = '/blog/'
  [permalinks.target]
    path = '/articles'
    [permalinks.target.sites]
      [permalinks.target.sites.matrix]
        languages = 'en'
[[permalinks]]
  pattern = '/blog/:year/:month/:slug/'
  [permalinks.target]
    path = '/articles/**'
    [permalinks.target.sites]
      [permalinks.target.sites.matrix]
        languages = 'en'
{
   "permalinks": [
      {
         "pattern": "/artikel/",
         "target": {
            "path": "/articles",
            "sites": {
               "matrix": {
                  "languages": "de"
               }
            }
         }
      },
      {
         "pattern": "/artikel/:year/:month/:slug/",
         "target": {
            "path": "/articles/**",
            "sites": {
               "matrix": {
                  "languages": "de"
               }
            }
         }
      },
      {
         "pattern": "/blog/",
         "target": {
            "path": "/articles",
            "sites": {
               "matrix": {
                  "languages": "en"
               }
            }
         }
      },
      {
         "pattern": "/blog/:year/:month/:slug/",
         "target": {
            "path": "/articles/**",
            "sites": {
               "matrix": {
                  "languages": "en"
               }
            }
         }
      }
   ]
}

To define a fallback that matches any page not already matched by a preceding entry, place an entry without a target key at the end:

permalinks:
- pattern: /:section/:slug/
[[permalinks]]
  pattern = '/:section/:slug/'
{
   "permalinks": [
      {
         "pattern": "/:section/:slug/"
      }
   ]
}

Tokens

Use these tokens when defining a URL pattern.

:year
The 4-digit year as defined in the front matter date field.
:month
The 2-digit month as defined in the front matter date field.
:monthname
The name of the month as defined in the front matter date field.
:day
The 2-digit day as defined in the front matter date field.
:weekday
The 1-digit day of the week as defined in the front matter date field (Sunday = 0).
:weekdayname
The name of the day of the week as defined in the front matter date field.
:yearday
The 1- to 3-digit day of the year as defined in the front matter date field.
:section
The content’s section.
:sectionslug
New in v0.149.0
The content’s section using slugified section name. The slugified section name is the slug as defined in front matter, else the title as defined in front matter, else the automatic title.
:sections
The content’s sections hierarchy. You can use a selection of the sections using slice syntax: :sections[1:] includes all but the first, :sections[:last] includes all but the last, :sections[last] includes only the last, :sections[1:2] includes section 2 and 3. Note that this slice access will not throw any out-of-bounds errors, so you don’t have to be exact.
:sectionslugs
New in v0.149.0
The content’s sections hierarchy using slugified section names. The slugified section name is the slug as defined in front matter, else the title as defined in front matter, else the automatic title. You can use a selection of the sections using slice syntax: :sectionslugs[1:] includes all but the first, :sectionslugs[:last] includes all but the last, :sectionslugs[last] includes only the last, :sectionslugs[1:2] includes section 2 and 3. Note that this slice access will not throw any out-of-bounds errors, so you don’t have to be exact.
:title
The title as defined in front matter, else the automatic title. Hugo generates titles automatically for section, taxonomy, and term pages that are not backed by a file.
:slug
The slug as defined in front matter, else the title as defined in front matter, else the automatic title. Hugo generates titles automatically for section, taxonomy, and term pages that are not backed by a file.
:filename
Deprecated in v0.144.0
Use the :contentbasename token instead.
:slugorfilename
Deprecated in v0.144.0
Use the :slugorcontentbasename token instead.
:contentbasename
New in v0.144.0
The content base name.
:slugorcontentbasename
New in v0.144.0
The slug as defined in front matter, else the content base name.

For time-related values, you can also use the layout string components defined in Go’s time package. For example:

permalinks:
  posts: /:06/:1/:2/:title/
[permalinks]
  posts = '/:06/:1/:2/:title/'
{
   "permalinks": {
      "posts": "/:06/:1/:2/:title/"
   }
}