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:
type | mediaType | weight | baseName | isHTML | isPlainText | noUgly | notAlternative | path | permalinkable | protocol | rel | root | ugly |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
amp | text/html | 0 | index | true | false | false | false | amp | true | amphtml | false | false | |
calendar | text/calendar | 0 | index | false | true | false | false | false | webcal:// | alternate | false | false | |
css | text/css | 0 | styles | false | true | false | true | false | stylesheet | false | false | ||
csv | text/csv | 0 | index | false | true | false | false | false | alternate | false | false | ||
html | text/html | 10 | index | true | false | false | false | true | canonical | false | false | ||
json | application/json | 0 | index | false | true | false | false | false | alternate | false | false | ||
markdown | text/markdown | 0 | index | false | true | false | false | false | alternate | false | false | ||
robots | text/plain | 0 | robots | false | true | false | false | false | alternate | true | false | ||
rss | application/rss+xml | 0 | index | false | false | true | false | false | alternate | false | false | ||
sitemap | application/xml | 0 | sitemap | false | false | false | false | false | sitemap | false | true | ||
webappmanifest | application/manifest+json | 0 | manifest | false | true | false | true | false | manifest | false | false |
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 isindex
. - 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 isfalse
. - isPlainText
- (
bool
) Whether to parse templates for this output format with Go’s text/template package instead of the html/template package. Default isfalse
. - 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 theAlternativeOutputFormats
method on aPage
object. Default isfalse
. - noUgly
- (
bool
) Whether to disable ugly URLs for this output format whenuglyURLs
are enabled in your site configuration. Default isfalse
. - 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 thePermalink
andRelPermalink
methods on aPage
object. See details. Enabled by default for thehtml
andamp
output formats. Default isfalse
. - protocol
- (
string
) The protocol (scheme) of the URL for this output format. For example,https://
orwebcal://
. Default is the scheme of thebaseURL
parameter in your site configuration, typicallyhttps://
. - rel
- (
string
) If provided, you can assign this value torel
attributes inlink
elements when iterating over output formats in your templates. Default isalternate
. - root
- (
bool
) Whether to publish files to the root of the publish directory. Default isfalse
. - ugly
- (
bool
) Whether to enable uglyURLs for this output format whenuglyURLs
isfalse
in your site configuration. Default isfalse
. - weight
- (
int
) When set to a non-zero value, Hugo uses theweight
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 is0
, except for thehtml
output format, which has a default weight of10
.
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 }}
Link to output formats
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 format | Template path |
---|---|
html | layouts/_default/section.html.html |
json | layouts/_default/section.json.json |
rss | layouts/_default/section.rss.xml |