HUGO
Menu
GitHub 88174 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, to configure URL patterns for the articles section:

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/"
      }
   }
}

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
      }
   }
}

Array form

New in v0.161.0

Define an array of permalink entries to apply different URL patterns to different subsets of pages. Each entry requires a pattern key. Hugo applies the first matching pattern.

The optional target key accepts a page matcher. If target is omitted, the 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 sites 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, to apply language-specific URL patterns to the articles section page and its leaf pages separately:

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 a pattern 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 :contentbasename instead.
:slugorfilename
Deprecated in v0.144.0
Use :slugorcontentbasename 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/"
   }
}