HUGO
News Docs Themes Community GitHub

Configure output formats

Configure output formats.

An output format is a collection of settings that defines how Hugo renders a file when building a site. For example, html, json, and rss are built-in output formats. You can create multiple output formats and control their generation based on page kind, or by enabling one or more output formats for specific pages.

You can output a page in as many formats as you want. Define an infinite number of output formats, provided they each resolve to a unique file system path.

This is the default output format configuration in tabular form:

typemediaTypeweightbaseNameisHTMLisPlainTextnoUglynotAlternativepathpermalinkableprotocolrelrootugly
amptext/html0indextruefalsefalsefalseamptrueamphtmlfalsefalse
calendartext/calendar0indexfalsetruefalsefalsefalsewebcal://alternatefalsefalse
csstext/css0stylesfalsetruefalsetruefalsestylesheetfalsefalse
csvtext/csv0indexfalsetruefalsefalsefalsealternatefalsefalse
htmltext/html10indextruefalsefalsefalsetruecanonicalfalsefalse
jsonapplication/json0indexfalsetruefalsefalsefalsealternatefalsefalse
markdowntext/markdown0indexfalsetruefalsefalsefalsealternatefalsefalse
robotstext/plain0robotsfalsetruefalsefalsefalsealternatetruefalse
rssapplication/rss+xml0indexfalsefalsetruefalsefalsealternatefalsefalse
sitemapapplication/xml0sitemapfalsefalsefalsefalsefalsesitemapfalsetrue
webappmanifestapplication/manifest+json0manifestfalsetruefalsetruefalsemanifestfalsefalse

Default configuration

The following is the default configuration that matches the table above:

outputFormats:
  amp:
    baseName: index
    isHTML: true
    isPlainText: false
    mediaType: text/html
    noUgly: false
    notAlternative: false
    path: amp
    permalinkable: true
    protocol: ""
    rel: amphtml
    root: false
    ugly: false
    weight: 0
  calendar:
    baseName: index
    isHTML: false
    isPlainText: true
    mediaType: text/calendar
    noUgly: false
    notAlternative: false
    path: ""
    permalinkable: false
    protocol: webcal://
    rel: alternate
    root: false
    ugly: false
    weight: 0
  css:
    baseName: styles
    isHTML: false
    isPlainText: true
    mediaType: text/css
    noUgly: false
    notAlternative: true
    path: ""
    permalinkable: false
    protocol: ""
    rel: stylesheet
    root: false
    ugly: false
    weight: 0
  csv:
    baseName: index
    isHTML: false
    isPlainText: true
    mediaType: text/csv
    noUgly: false
    notAlternative: false
    path: ""
    permalinkable: false
    protocol: ""
    rel: alternate
    root: false
    ugly: false
    weight: 0
  html:
    baseName: index
    isHTML: true
    isPlainText: false
    mediaType: text/html
    noUgly: false
    notAlternative: false
    path: ""
    permalinkable: true
    protocol: ""
    rel: canonical
    root: false
    ugly: false
    weight: 10
  json:
    baseName: index
    isHTML: false
    isPlainText: true
    mediaType: application/json
    noUgly: false
    notAlternative: false
    path: ""
    permalinkable: false
    protocol: ""
    rel: alternate
    root: false
    ugly: false
    weight: 0
  markdown:
    baseName: index
    isHTML: false
    isPlainText: true
    mediaType: text/markdown
    noUgly: false
    notAlternative: false
    path: ""
    permalinkable: false
    protocol: ""
    rel: alternate
    root: false
    ugly: false
    weight: 0
  robots:
    baseName: robots
    isHTML: false
    isPlainText: true
    mediaType: text/plain
    noUgly: false
    notAlternative: false
    path: ""
    permalinkable: false
    protocol: ""
    rel: alternate
    root: true
    ugly: false
    weight: 0
  rss:
    baseName: index
    isHTML: false
    isPlainText: false
    mediaType: application/rss+xml
    noUgly: true
    notAlternative: false
    path: ""
    permalinkable: false
    protocol: ""
    rel: alternate
    root: false
    ugly: false
    weight: 0
  sitemap:
    baseName: sitemap
    isHTML: false
    isPlainText: false
    mediaType: application/xml
    noUgly: false
    notAlternative: false
    path: ""
    permalinkable: false
    protocol: ""
    rel: sitemap
    root: false
    ugly: true
    weight: 0
  webappmanifest:
    baseName: manifest
    isHTML: false
    isPlainText: true
    mediaType: application/manifest+json
    noUgly: false
    notAlternative: true
    path: ""
    permalinkable: false
    protocol: ""
    rel: manifest
    root: false
    ugly: false
    weight: 0
[outputFormats]
  [outputFormats.amp]
    baseName = 'index'
    isHTML = true
    isPlainText = false
    mediaType = 'text/html'
    noUgly = false
    notAlternative = false
    path = 'amp'
    permalinkable = true
    protocol = ''
    rel = 'amphtml'
    root = false
    ugly = false
    weight = 0
  [outputFormats.calendar]
    baseName = 'index'
    isHTML = false
    isPlainText = true
    mediaType = 'text/calendar'
    noUgly = false
    notAlternative = false
    path = ''
    permalinkable = false
    protocol = 'webcal://'
    rel = 'alternate'
    root = false
    ugly = false
    weight = 0
  [outputFormats.css]
    baseName = 'styles'
    isHTML = false
    isPlainText = true
    mediaType = 'text/css'
    noUgly = false
    notAlternative = true
    path = ''
    permalinkable = false
    protocol = ''
    rel = 'stylesheet'
    root = false
    ugly = false
    weight = 0
  [outputFormats.csv]
    baseName = 'index'
    isHTML = false
    isPlainText = true
    mediaType = 'text/csv'
    noUgly = false
    notAlternative = false
    path = ''
    permalinkable = false
    protocol = ''
    rel = 'alternate'
    root = false
    ugly = false
    weight = 0
  [outputFormats.html]
    baseName = 'index'
    isHTML = true
    isPlainText = false
    mediaType = 'text/html'
    noUgly = false
    notAlternative = false
    path = ''
    permalinkable = true
    protocol = ''
    rel = 'canonical'
    root = false
    ugly = false
    weight = 10
  [outputFormats.json]
    baseName = 'index'
    isHTML = false
    isPlainText = true
    mediaType = 'application/json'
    noUgly = false
    notAlternative = false
    path = ''
    permalinkable = false
    protocol = ''
    rel = 'alternate'
    root = false
    ugly = false
    weight = 0
  [outputFormats.markdown]
    baseName = 'index'
    isHTML = false
    isPlainText = true
    mediaType = 'text/markdown'
    noUgly = false
    notAlternative = false
    path = ''
    permalinkable = false
    protocol = ''
    rel = 'alternate'
    root = false
    ugly = false
    weight = 0
  [outputFormats.robots]
    baseName = 'robots'
    isHTML = false
    isPlainText = true
    mediaType = 'text/plain'
    noUgly = false
    notAlternative = false
    path = ''
    permalinkable = false
    protocol = ''
    rel = 'alternate'
    root = true
    ugly = false
    weight = 0
  [outputFormats.rss]
    baseName = 'index'
    isHTML = false
    isPlainText = false
    mediaType = 'application/rss+xml'
    noUgly = true
    notAlternative = false
    path = ''
    permalinkable = false
    protocol = ''
    rel = 'alternate'
    root = false
    ugly = false
    weight = 0
  [outputFormats.sitemap]
    baseName = 'sitemap'
    isHTML = false
    isPlainText = false
    mediaType = 'application/xml'
    noUgly = false
    notAlternative = false
    path = ''
    permalinkable = false
    protocol = ''
    rel = 'sitemap'
    root = false
    ugly = true
    weight = 0
  [outputFormats.webappmanifest]
    baseName = 'manifest'
    isHTML = false
    isPlainText = true
    mediaType = 'application/manifest+json'
    noUgly = false
    notAlternative = true
    path = ''
    permalinkable = false
    protocol = ''
    rel = 'manifest'
    root = false
    ugly = false
    weight = 0
{
   "outputFormats": {
      "amp": {
         "baseName": "index",
         "isHTML": true,
         "isPlainText": false,
         "mediaType": "text/html",
         "noUgly": false,
         "notAlternative": false,
         "path": "amp",
         "permalinkable": true,
         "protocol": "",
         "rel": "amphtml",
         "root": false,
         "ugly": false,
         "weight": 0
      },
      "calendar": {
         "baseName": "index",
         "isHTML": false,
         "isPlainText": true,
         "mediaType": "text/calendar",
         "noUgly": false,
         "notAlternative": false,
         "path": "",
         "permalinkable": false,
         "protocol": "webcal://",
         "rel": "alternate",
         "root": false,
         "ugly": false,
         "weight": 0
      },
      "css": {
         "baseName": "styles",
         "isHTML": false,
         "isPlainText": true,
         "mediaType": "text/css",
         "noUgly": false,
         "notAlternative": true,
         "path": "",
         "permalinkable": false,
         "protocol": "",
         "rel": "stylesheet",
         "root": false,
         "ugly": false,
         "weight": 0
      },
      "csv": {
         "baseName": "index",
         "isHTML": false,
         "isPlainText": true,
         "mediaType": "text/csv",
         "noUgly": false,
         "notAlternative": false,
         "path": "",
         "permalinkable": false,
         "protocol": "",
         "rel": "alternate",
         "root": false,
         "ugly": false,
         "weight": 0
      },
      "html": {
         "baseName": "index",
         "isHTML": true,
         "isPlainText": false,
         "mediaType": "text/html",
         "noUgly": false,
         "notAlternative": false,
         "path": "",
         "permalinkable": true,
         "protocol": "",
         "rel": "canonical",
         "root": false,
         "ugly": false,
         "weight": 10
      },
      "json": {
         "baseName": "index",
         "isHTML": false,
         "isPlainText": true,
         "mediaType": "application/json",
         "noUgly": false,
         "notAlternative": false,
         "path": "",
         "permalinkable": false,
         "protocol": "",
         "rel": "alternate",
         "root": false,
         "ugly": false,
         "weight": 0
      },
      "markdown": {
         "baseName": "index",
         "isHTML": false,
         "isPlainText": true,
         "mediaType": "text/markdown",
         "noUgly": false,
         "notAlternative": false,
         "path": "",
         "permalinkable": false,
         "protocol": "",
         "rel": "alternate",
         "root": false,
         "ugly": false,
         "weight": 0
      },
      "robots": {
         "baseName": "robots",
         "isHTML": false,
         "isPlainText": true,
         "mediaType": "text/plain",
         "noUgly": false,
         "notAlternative": false,
         "path": "",
         "permalinkable": false,
         "protocol": "",
         "rel": "alternate",
         "root": true,
         "ugly": false,
         "weight": 0
      },
      "rss": {
         "baseName": "index",
         "isHTML": false,
         "isPlainText": false,
         "mediaType": "application/rss+xml",
         "noUgly": true,
         "notAlternative": false,
         "path": "",
         "permalinkable": false,
         "protocol": "",
         "rel": "alternate",
         "root": false,
         "ugly": false,
         "weight": 0
      },
      "sitemap": {
         "baseName": "sitemap",
         "isHTML": false,
         "isPlainText": false,
         "mediaType": "application/xml",
         "noUgly": false,
         "notAlternative": false,
         "path": "",
         "permalinkable": false,
         "protocol": "",
         "rel": "sitemap",
         "root": false,
         "ugly": true,
         "weight": 0
      },
      "webappmanifest": {
         "baseName": "manifest",
         "isHTML": false,
         "isPlainText": true,
         "mediaType": "application/manifest+json",
         "noUgly": false,
         "notAlternative": true,
         "path": "",
         "permalinkable": false,
         "protocol": "",
         "rel": "manifest",
         "root": false,
         "ugly": false,
         "weight": 0
      }
   }
}
baseName
(string) The base name of the published file. Default is index.
isHTML
(bool) Whether to classify the output format as HTML. Hugo uses this value to determine when to create alias redirects and when to inject the LiveReload script. Default is false.
isPlainText
(bool) Whether to parse templates for this output format with Go’s text/template package instead of the html/template package. Default is false.
mediaType
(string) The media type of the published file. This must match one of the configured media types.
notAlternative
(bool) Whether to exclude this output format from the values returned by the AlternativeOutputFormats method on a Page object. Default is false.
noUgly
(bool) Whether to disable ugly URLs for this output format when uglyURLs are enabled in your site configuration. Default is false.
path
(string) The published file’s directory path, relative to the root of the publish directory. If not specified, the file will be published using its content path.
permalinkable
(bool) Whether to return the rendering output format rather than main output format when invoking the Permalink and RelPermalink methods on a Page object. See details. Enabled by default for the html and amp output formats. Default is false.
protocol
(string) The protocol (scheme) of the URL for this output format. For example, https:// or webcal://. Default is the scheme of the baseURL parameter in your site configuration, typically https://.
rel
(string) If provided, you can assign this value to rel attributes in link elements when iterating over output formats in your templates. Default is alternate.
root
(bool) Whether to publish files to the root of the publish directory. Default is false.
ugly
(bool) Whether to enable uglyURLs for this output format when uglyURLs is false in your site configuration. Default is false.
weight
(int) When set to a non-zero value, Hugo uses the weight as the first criteria when sorting output formats, falling back to the name of the output format. Lighter items float to the top, while heavier items sink to the bottom. Hugo renders output formats sequentially based on the sort order. Default is 0, except for the html output format, which has a default weight of 10.

Modify an output format

You can modify any of the default output formats. For example, to prioritize json rendering over html rendering, when both are generated, adjust the weight:

outputFormats:
  html:
    weight: 2
  json:
    weight: 1
[outputFormats]
  [outputFormats.html]
    weight = 2
  [outputFormats.json]
    weight = 1
{
   "outputFormats": {
      "html": {
         "weight": 2
      },
      "json": {
         "weight": 1
      }
   }
}

The example above shows that when you modify a default content format, you only need to define the properties that differ from their default values.

Create an output format

You can create new output formats as needed. For example, you may wish to create an output format to support Atom feeds.

Step 1

You must specify a media type when you create an output format. Because application/atom+xml, the media type for Atom feeds, is not a default media type, begin by creating a new one:

mediaTypes:
  application/atom+xml:
    suffixes:
    - atom
[mediaTypes]
  [mediaTypes.'application/atom+xml']
    suffixes = ['atom']
{
   "mediaTypes": {
      "application/atom+xml": {
         "suffixes": [
            "atom"
         ]
      }
   }
}

See configure media types for more information.

Step 2

Create a new output format:

outputFormats:
  atom:
    mediaType: application/atom+xml
    noUgly: true
[outputFormats]
  [outputFormats.atom]
    mediaType = 'application/atom+xml'
    noUgly = true
{
   "outputFormats": {
      "atom": {
         "mediaType": "application/atom+xml",
         "noUgly": true
      }
   }
}

Note that we use the default settings for all other output format properties.

Step 3

Specify the page kinds for which to render this output format:

outputs:
  home:
  - html
  - rss
  - atom
  section:
  - html
  - rss
  - atom
  taxonomy:
  - html
  - rss
  - atom
  term:
  - html
  - rss
  - atom
[outputs]
  home = ['html', 'rss', 'atom']
  section = ['html', 'rss', 'atom']
  taxonomy = ['html', 'rss', 'atom']
  term = ['html', 'rss', 'atom']
{
   "outputs": {
      "home": [
         "html",
         "rss",
         "atom"
      ],
      "section": [
         "html",
         "rss",
         "atom"
      ],
      "taxonomy": [
         "html",
         "rss",
         "atom"
      ],
      "term": [
         "html",
         "rss",
         "atom"
      ]
   }
}

See configure outputs for more information.

Step 4

Create a template to render the output format. Since Atom feeds are lists, you need to create a list template. Consult the template lookup order to find the correct template path:

layouts/_default/list.atom.atom

We leave writing the template code as an exercise for you. Aim for a result similar to the embedded RSS template.

List output formats

To access output formats, each Page object provides two methods: OutputFormats (for all formats, including the current one) and AlternativeOutputFormats. Use AlternativeOutputFormats to create a link rel list within your site’s head element, as shown below:

{{ range .AlternativeOutputFormats -}}
  <link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}">
{{ end }}

By default, a Page object’s Permalink and RelPermalink methods return the URL of the primary output format, typically html. This behavior remains consistent regardless of the template used.

For example, in single.json.json, you’ll see:

{{ .RelPermalink }} → /that-page/
{{ with .OutputFormats.Get "json" }}
  {{ .RelPermalink }} → /that-page/index.json
{{ end }}

To make these methods return the URL of the current template’s output format, you must set the permalinkable setting to true for that format.

With permalinkable set to true for json in the same single.json.json template:

{{ .RelPermalink }} → /that-page/index.json
{{ with .OutputFormats.Get "html" }}
  {{ .RelPermalink }} → /that-page/
{{ end }}

Template lookup order

Each output format requires a template conforming to the template lookup order.

For the highest specificity in the template lookup order, include the page kind, output format, and suffix in the file name:

[page kind].[output format].[suffix]

For example, for section pages:

Output formatTemplate path
htmllayouts/_default/section.html.html
jsonlayouts/_default/section.json.json
rsslayouts/_default/section.rss.xml