You can convert your articles into JSON objects by creating a series of templates in your theme. These templates can adhere to any JSON schema you choose.
The JSON output format is advantageous for documentation sites because it can be used to build search indexes, chatbots, dashboards, and other applications that require structured data.
Before you start #
- Review the Page Kinds Hugo Documentation
- Review the Front Matter Hugo Documentation
- Review the Page Methods Hugo Documentation
How to create JSON output #
Create json.json partial #
This template acts as the core of your JSON Schema definition. It will be used across all of the other page kind layouts we’ll build (single.json
, section.json
, list.json
, home.json
).
-
Navigate to your theme’s
layouts/partials
directory. -
Create a new file called
json.json
. -
Define the schema you want. Here is an example:
{ "id": "", "version": "", "title": "", "description": "", "date": "", "draft": "", "hidden": "", "lastCommit": "", "section": "", "parent": "", "pageKind": "", "content": "", "permalink": "", "relPermalink": "" }
-
Add golang template logic to each attribute. This requires you to use a series of page methods for pulling in data. If you’d like to use a custom front matter attribute, such as a cascaded
version
number from a parent directory’s_index.md
, remember to use the.Params
method to access it.{ "id": "{{ .File.UniqueID }}", "version": "{{.Params.version}}", "title": "{{ .Title }}", "description": "{{ .Description }}", "date": "{{ .Date }}", "draft": {{ .Draft }}, "hidden": {{ .Hidden }}, "lastCommit": "{{ .GitInfo.AuthorDate }}", "section": "{{ .Section }}", "parent": "{{ .Parent }}", "pageKind": "{{ .Type }}", "bundleType": "{{ .BundleType }}", "content": "{{ .Content }}", "permalink": "{{ .Permalink }}", "relPermalink": "{{ .RelPermalink }}", }
You can conditionally include or exclude certain attributes. For example, you can exclude the
hidden
attribute if it is not set in the front matter.{{- with .Page.Params.hidden -}}"hidden": {{- . -}},{{- end -}}
-
Save the file.
Create default layouts #
single.json #
This template will be used to render the JSON object for the page
page kind.
- Navigate to your theme’s
layouts/_default
directory. - Create a new file called
single.json
. - Add the following code:
{{- partial "json.json" . -}}
- Save the file.
section.json #
This template will be used to render the JSON object for the section
page kind. A section is a page that contains an array of page kinds (that can also include other sections!). Knowing this, we need to create a recursive template that will render the JSON object for the section and all of its descendants.
- Navigate to your theme’s
layouts/_default
directory. - Create a new file called
section.json
. - Add the following code:
[ {{- range $index, $page := .Pages }} {{- if ne $page.Type "json" }} {{- if and $index (gt $index 0) }},{{ end }} {{- partial "json.json" . }} {{- end }} {{- if eq .Kind "section"}} {{- template "section" . }} {{- end }} {{- end }} ] {{- define "section" }} {{- range .Pages }} {{- if ne .Type "json" }} ,{{- partial "json.json" . }} {{- end }} {{- if eq .Kind "section"}} {{- template "section" . }} {{- end }} {{- end }} {{- end }}
There may be a more elegant way to define this template, but this one does work. If you come up with a better one please share! - Save the file.
list.json #
This template will be used to render the JSON object for the list
page kind.
- Navigate to your theme’s
layouts/_default
directory. - Create a new file called
list.json
. - Add the following code:
{{- partial "json.json" . -}}
- Save the file.
home.json #
This template will be used to render the JSON object for the home
page kind.
- Navigate to your theme’s
layouts/_default
directory. - Create a new file called
home.json
. - Add the following code:
[ {{- range $index, $page := .Pages }} {{- if ne $page.Type "json" }} {{- if and $index (gt $index 0) }},{{- end }} {{- partial "json.json" . }} {{- end }} {{- if eq .Kind "section" }} {{- template "section" . }} {{- end }} {{- end }} ] {{- define "section" }} {{- range .Pages }} {{- if ne .Type "json" }} ,{{- partial "json.json" . }} {{- end }} {{- if eq .Kind "section"}} {{- template "section" . }} {{- end }} {{- end }} {{- end }}
- Save the file.
Update Hugo configuration #
- Open your Hugo
outputs
configuration (for example,config/_default/outputs.yaml
). - Update each page kind to include JSON in the supported array.
home: [ "HTML", "JSON"] page: [ "HTML", "JSON"] section: [ "HTML", "JSON"] list: [ "HTML", "JSON"]
- Save the file.
Test #
- Run
hugo server
in your project directory. - Navigate to your site’s homepage and append
/index.json
to the URL. You should see a JSON index of all of your site’s pages. You can append/index.json
to any url whose page is built using these supported page kind layouts.
Now you can use the JSON output to build search indexes, chatbots, dashboards, and other applications that require structured data.