thesatelliteoflove/content/posts/add-a-json-feed-to-any-hugo-site.md
Phil f2526f6c62
All checks were successful
Build Hugo Site / build (push) Successful in 9s
took it out of draft mode
2024-12-27 20:30:51 -07:00

108 lines
3.8 KiB
Markdown

---
title: "Add a Json Feed to Any Hugo Site"
date: 2024-12-27T20:13:26-07:00
draft: false
toc: false
description: "I fought with Hugo to add a JSON Feed so you don't have to #hugo #posse"
images:
tags:
- posse
- hugo
---
Super quick post tonight as a precursor to a post that I am working on about me adopting a "Post Once Syndicate Everywhere" ([POSSE](https://indieweb.org/POSSE)) strategy for my content.
I just spent way too long wrestling with Hugo (which runs this site) to add a [JSON Feed](https://www.jsonfeed.org/) compatible feed so that I can more reliably publish updates to this blog to the Fediverse/Threads/Bluesky and discovered that, ultimately, it is actually really simple. So I decided t document here in case anyone else needs a hand.
1. Add the following to your hugo.toml file
```
[outputFormats.jsonfeed]
mediaType = "application/json"
baseName = "feed"
rel = "alternate"
isPlainText = true
[outputs]
home = ["html", "jsonfeed", "rss"]
section = ["html", "jsonfeed", "rss"]
```
This creates the JSON Feed output format and adds the outputs to both "Home" and each section (for example, Posts).
2. In the root of your project (no need to mess with the theme if you are using one) make sure you have a layouts folder, and a _default folder inside of it (so layouts/_default)
3. In the layouts/_default directory create list.jsonfeed.json and copy the following into it:
```
{{- $pctx := . -}}
{{- if .IsHome -}}{{ $pctx = site }}{{- end -}}
{{- $pages := slice -}}
{{- if or $.IsHome $.IsSection -}}
{{- $pages = $pctx.RegularPages -}}
{{- else -}}
{{- $pages = $pctx.Pages -}}
{{- end -}}
{{- $limit := site.Config.Services.RSS.Limit -}}
{{- if ge $limit 1 -}}
{{- $pages = $pages | first $limit -}}
{{- end -}}
{{- $title := "" }}
{{- if eq .Title .Site.Title }}
{{- $title = .Site.Title }}
{{- else }}
{{- with .Title }}
{{- $title = print . " on "}}
{{- end }}
{{- $title = print $title .Site.Title }}
{{- end }}
{
"version": "https://jsonfeed.org/version/1.1",
"title": {{ $title | jsonify }},
"home_page_url": {{ .Permalink | jsonify }},
{{- with .OutputFormats.Get "jsonfeed" }}
"feed_url": {{ .Permalink | jsonify }},
{{- end }}
{{- if (or .Site.Params.author .Site.Params.author_url) }}
"authors": [{
{{- if .Site.Params.author }}
"name": {{ .Site.Params.author | jsonify }},
{{- end }}
{{- if .Site.Params.author_url }}
"url": {{ .Site.Params.author_url | jsonify }}
{{- end }}
}],
{{- end }}
{{- if $pages }}
"items": [
{{- range $index, $element := $pages }}
{{- with $element }}
{{- if $index }},{{end}} {
"title": {{ .Title | jsonify }},
"id": {{ .Permalink | jsonify }},
"tags": ["{{ delimit .Params.tags "," }}"]
"url": {{ .Permalink | jsonify }},
{{- if .Site.Params.showFullTextinJSONFeed }}
"summary": {{ with .Description }}{{ . | jsonify }}{{ else }}{{ .Summary | jsonify }}{{ end -}},
"content_html": {{ .Content | jsonify }},
{{- else }}
"content_text": {{ with .Description }}{{ . | jsonify }}{{ else }}{{ .Summary | jsonify }}{{ end -}},
{{- end }}
{{- if .Params.cover.image }}
{{- $cover := (.Resources.ByType "image").GetMatch (printf "*%s*" (.Params.cover.image)) }}
{{- if $cover }}
"image": {{ (path.Join .RelPermalink $cover) | absURL | jsonify }},
{{- end }}
{{- end }}
"date_published": {{ .Date.Format "2006-01-02T15:04:05Z07:00" | jsonify }}
}
{{- end }}
{{- end }}
]
{{ end }}
}
```
This lets Hugo know how to format these feeds.
... And that's it! You can check out my JSON feed at https://thesatelliteoflove.com/posts/feed/json