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 any number of output formats, provided each resolves 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 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 404 | text/html | 0 | true | false | false | true | true | false | true | ||||
| alias | text/html | 0 | true | false | false | false | false | false | true | ||||
| 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 | ||
| gotmpl | text/x-gotmpl | 0 | false | true | false | true | false | 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 | ||
| sitemapindex | application/xml | 0 | sitemap | false | false | false | false | false | sitemap | true | true | ||
| webappmanifest | application/manifest+json | 0 | manifest | false | true | false | true | false | manifest | false | false |
Default configuration
This is the default configuration that matches the table above:
outputFormats:
'404':
baseName: ''
isHTML: true
isPlainText: false
mediaType: text/html
noUgly: false
notAlternative: true
path: ''
permalinkable: true
protocol: ''
rel: ''
root: false
ugly: true
weight: 0
alias:
baseName: ''
isHTML: true
isPlainText: false
mediaType: text/html
noUgly: false
notAlternative: false
path: ''
permalinkable: false
protocol: ''
rel: ''
root: false
ugly: true
weight: 0
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
gotmpl:
baseName: ''
isHTML: false
isPlainText: true
mediaType: text/x-gotmpl
noUgly: false
notAlternative: true
path: ''
permalinkable: false
protocol: ''
rel: ''
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
sitemapindex:
baseName: sitemap
isHTML: false
isPlainText: false
mediaType: application/xml
noUgly: false
notAlternative: false
path: ''
permalinkable: false
protocol: ''
rel: sitemap
root: true
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.404]
baseName = ''
isHTML = true
isPlainText = false
mediaType = 'text/html'
noUgly = false
notAlternative = true
path = ''
permalinkable = true
protocol = ''
rel = ''
root = false
ugly = true
weight = 0
[outputFormats.alias]
baseName = ''
isHTML = true
isPlainText = false
mediaType = 'text/html'
noUgly = false
notAlternative = false
path = ''
permalinkable = false
protocol = ''
rel = ''
root = false
ugly = true
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
[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.gotmpl]
baseName = ''
isHTML = false
isPlainText = true
mediaType = 'text/x-gotmpl'
noUgly = false
notAlternative = true
path = ''
permalinkable = false
protocol = ''
rel = ''
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.sitemapindex]
baseName = 'sitemap'
isHTML = false
isPlainText = false
mediaType = 'application/xml'
noUgly = false
notAlternative = false
path = ''
permalinkable = false
protocol = ''
rel = 'sitemap'
root = true
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": {
"404": {
"baseName": "",
"isHTML": true,
"isPlainText": false,
"mediaType": "text/html",
"noUgly": false,
"notAlternative": true,
"path": "",
"permalinkable": true,
"protocol": "",
"rel": "",
"root": false,
"ugly": true,
"weight": 0
},
"alias": {
"baseName": "",
"isHTML": true,
"isPlainText": false,
"mediaType": "text/html",
"noUgly": false,
"notAlternative": false,
"path": "",
"permalinkable": false,
"protocol": "",
"rel": "",
"root": false,
"ugly": true,
"weight": 0
},
"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
},
"gotmpl": {
"baseName": "",
"isHTML": false,
"isPlainText": true,
"mediaType": "text/x-gotmpl",
"noUgly": false,
"notAlternative": true,
"path": "",
"permalinkable": false,
"protocol": "",
"rel": "",
"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
},
"sitemapindex": {
"baseName": "sitemap",
"isHTML": false,
"isPlainText": false,
"mediaType": "application/xml",
"noUgly": false,
"notAlternative": false,
"path": "",
"permalinkable": false,
"protocol": "",
"rel": "sitemap",
"root": true,
"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. This value determines when Hugo injects the LiveReload script and, together withpermalinkable, whether Hugo generates alias redirects. Default isfalse. isPlainText- (
bool) Whether to treat the output of templates for this output format as plain text instead of HTML. Set this totruefor output formats where HTML escaping would corrupt the output, such as JSON or CSV. Default isfalse. The table below shows how the setting affects templates.Effect falsetrueHow Hugo prints values Hugo escapes values, so that the output is safe to use in HTML. For example, <becomes<.Hugo prints values without escaping them. Return type for partials.Includeandpartials.IncludeCachedtemplate.HTMLstringGo package used to parse templates html/templatetext/templateTo print a value from a trusted source without escaping it, declare it safe. See safe types for details.
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 theAlternativeOutputFormatsmethod on aPageobject. Default isfalse. noUgly- (
bool) Whether to disable ugly URLs for this output format whenuglyURLsare enabled in your project configuration. Default isfalse. path- (
string) The first segment of the publication path for this output format. This path segment is relative to the root of yourpublicdirectory. If omitted, Hugo uses the file’s original content path for publishing. permalinkable- (
bool) Whether to return the rendering output format rather than the main output format when invoking thePermalinkandRelPermalinkmethods on aPageobject. Along withisHTML, this must betrueto create alias redirects. Default isfalse, except for thehtml,amp, and404output formats, where the default istrue. protocol- (
string) The protocol (scheme) of the URL for this output format. For example,https://orwebcal://. Default is the scheme of thebaseURLparameter in your project configuration, typicallyhttps://. rel- (
string) The relationship of the output format to the current page. Hugo uses this property to determine the canonical output format of the current page. For the predefinedhtmloutput format, the default value iscanonical. For all other predefined output formats, the default value isalternate. root- (
bool) Whether to publish files to the root of thepublicdirectory. Default isfalse. ugly- (
bool) Whether to enable ugly URLs for this output format whenuglyURLsisfalsein your project configuration. Default isfalse. weight- (
int) When set to a non-zero value, Hugo uses theweightas the first criterion 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 thehtmloutput format, which has a default weight of10.
Modify an output format
You can modify any of the default output formats. For example, adjust the weight to render json before html when Hugo generates both:
outputFormats:
html:
weight: 2
json:
weight: 1
[outputFormats]
[outputFormats.html]
weight = 2
[outputFormats.json]
weight = 1
{
"outputFormats": {
"html": {
"weight": 2
},
"json": {
"weight": 1
}
}
}
When you modify a default output 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, follow these steps to create an output format for Atom feeds.
- Step 1
- Each output format requires a media type. Atom feeds use
application/atom+xml, which is not one of the default media types, so create it first.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 } } }The new output format uses the default settings for all other 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. Atom feeds are lists, so create a list template. Use the template lookup order to find the correct template path:
layouts/list.atom.atomUse the embedded RSS template as a model for your template.
List output formats
Each Page object provides two methods to access output formats. The OutputFormats method returns all output formats, including the current one, and the AlternativeOutputFormats method returns all output formats except the current one. For example, use the AlternativeOutputFormats method to create a link element for each alternative output format within the head element:
{{ range .AlternativeOutputFormats }}
<link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}">
{{ end }}Link to output formats
The URL returned by a Page object’s Permalink and RelPermalink methods depends on the current output format. For output formats with permalinkable set to true, such as html and amp, the methods return that format’s own URL. For all other output formats, the methods return the URL of the page’s primary output format.
For example, in a page.json.json template, these methods return these values:
{{ .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, set permalinkable to true for that format.
With permalinkable set to true for the json output format, in the same page.json.json template, these methods return these values:
{{ .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, the table below shows the template path for section pages in each of three output formats.
| Output format | Template path |
|---|---|
html | layouts/section.html.html |
json | layouts/section.json.json |
rss | layouts/section.rss.xml |
