jekyll-feed: You aren't gonna need it

I think I’m going to turn this into a series of posts, about a lot of popular Jekyll plugins - and how you just aren’t gonna need them. We’ll see how far we get. And where better to start than jekyll-feed? The popular feed plug-in that publishes an Atom feed that includes your 10 most recent posts, no more, no less, and no option to configure that number.

This bugs me. I’ve seen Feedly do annoying things with a small number of feeds in the past. I have some feeds I like to read periodically, but not regularly. Very rarely some of these same feeds would start disappearing their old items far too quickly (like within a few weeks, not a month). But I digress, and maybe this didn’t have anything to do with their feeds.

In any case 10 seems like a completely arbitrary number to me and also a bit small for my personal tastes. Thankfully, you don’t need jekyll-feed or it’s limitations. I glanced at Daring Fireball’s atom.xml feed for a little inspiration and just built my own from there. Here’s what it looks like:

atom.xml

---
layout: null
---
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 <title>{{ site.title | xml_escape }}</title>
 <subtitle>{{ site.description | xml_escape }}</subtitle>
 <link href="{{ site.url }}/atom.xml" rel="self" type="application/atom+xml"/>
 <link href="{{ site.url }}/" rel="alternate" type="text/html"/>
 <id>{{ site.url }}/</id>
 <generator uri="https://jekyllrb.com/" version="{{ jekyll.version }}">Jekyll</generator>

 <updated>{{ site.time | date_to_xmlschema }}</updated>

 <author>
   <name>{{ site.author.name | xml_escape }}</name>
   <email>{{ site.author.email | xml_escape }}</email>
   <uri>{{ site.author.url | xml_escape }}</uri>·
 </author>
 <rights>Copyright © {{site.time |date: "%Y" }} {{site.author.name}}</rights>

 {% for post in site.posts limit:30 %}
 <entry>
   <title><![CDATA[{{ post.title }}]]></title>
   {%- if post.link_to %}
   <link rel="alternate" type="text/html" href="{{ post.link_to }}"/>
   <link rel="related" type="text/html" href="{{ site.url }}{{ post.url }}"/>
   {%- else %}
   <link rel="alternate" type="text/html" href="{{ site.url }}{{ post.url }}"/>
   {%- endif %}
   <id>{{ site.url }}{{ post.id }}</id>
   <published>{{ post.date | date_to_xmlschema }}</published>
   <updated>{{ post.last_modified_at | default: post.date | date_to_xmlschema }}</updated>
   <content type="html"><![CDATA[
     {{ post.content | markdownify }}
   ]]></content>
 </entry>
 {% endfor %}

</feed>

The post.link_to conditional is just how I do my link/commentary style posts - allowing the default link to point the content itself rather than to my blog post. If your use case is simpler just remover that if/else; and that’s half the point of just using a template rather than a plug-in - so easy to bend to your own use.

Why alternate between CDATA and xml_escape? No reason. I may just as likely go back and change them all to CDATA later. It that’s your style, go for it. My goal here isn’t to say “use my great templates” or to publish another feed plug-in - it’s to point out how easy this all is to do it yourself - the way you want.

But perhaps you’ve head XML is dead or at the very least it sucks.

feed.json

---
layout: null·
---
{
  "version": "https://jsonfeed.org/version/1",
  "title": "{{site.title}}",
  "home_page_url": "{{site.url}}",
  "feed_url": "{{site.url}}{{site.json_feed}}",
  "author" : {
    "name" : "{{site.author.name}}",
    "url" : "{{site.author.url}}"
  },
  "icon" : "",
  "favicon" : "",
  "items": [
  {%- for post in site.posts limit:30 %}
  {
    "title": {{ post.title | jsonify }},
    "date_published" : {{ post.date | date_to_xmlschema | jsonify }},
    "date_modified" : {{ post.last_modified_at | default: post.date | date_to_xmlschema | jsonify}},
    "id" : "{{ site.url }}{{ post.id }}",
    "url" : "{{ site.url }}{{ post.id }}",
    {%- if post.link_to %}
    "external_url" : {{ post.link_to | jsonify }},
    {%- endif %}
    "author" : {
      "name" : {{site.author.name | jsonify }}
    },
    "content_html" : {{ post.content | markdownify | jsonify }}·
  }{% if forloop.last == false %},{% endif %}{%- endfor %}
  ]
}

And of course don’t forget to add your fancy new feeds to the <head> section of your template:

<link rel="alternate" type="application/atom+xml" href="{{site.url}}/atom.xml" />
<link rel="alternate" type="application/json" href="{{site.url}}/feed.json" />