Adding an RSS feed to a Blog
Tags: rss, eleventy
Published: 2021-10-05 01:20:43

I have a personal blog I built on Eleventy and published on several hosting services.  One problem is that I don't write posts on it very often because I'm usually busy doing other things.  So if you were someone interested in that content you'd be forced to check it day-after-day in vain so see if I've done anything new.  What would be better is if users could subscribe to content.

This idea is interesting because of how politics shaped the web.  It used to be very standard to have RSS (Really Simple Syndication) feeds, or Atom feeds.  This is sadly no longer the case.  Most subscription data is handled through social media or the platforms themselves in a siloed way.  In fact Google rather famously killed one of the biggest RSS readers, Google Reader, probably because of the incentives to funnel more of that content through themselves direction.  Still RSS is supported by many things and is the ideal target for someone making a small independent content feed even if feels old.  In fact it's still used quite commonly in the podcast world.

## How RSS works

RSS started when XML was all the rage, so it is an XML document.  Simply, you add entries to the document as you post new content.  An RSS reader is an app that can consume RSS content.  Typically you give it an RSS url and it will poll the RSS feed document at regular intervals (the RSS document can give hints on how often stuff is posted to make this more efficient).  As new entries are seen in the feed it can alert the user that there's something new to view.

## RSS Structure

The RSS spec is surprisingly readable and easy to follow.  I'm just giving a summary but there's a lot of stuff I won't mention that might be relevant to certain scenarios.  I highly suggest you follow along: https://validator.w3.org/feed/docs/rss2.html

### RSS

First we start with the `<rss>` tag, analogous to the `<html>` tag it encompasses the document.  It has an single mandatory attribute called "version".  RSS hasn't changed in the very long time so the latest is "2.0".

### Channel

Next is the `<channel>`, there's only one and it contains some metadata about the feed.  Rather than attributes it has child elements that describe the feed.  Of these you need `<title>`, `<description>` and `<link>`.  Title and description are pretty obvious they are the title and description of the feed, the link is the link to the content such as the blog homepage.  Other sub-elements of interest are `<langauge>` which I use value `en-us`, `lastBuildDate` which is when you last generated the feed file, `skipHours` and `skipDays` which are the hints for when the reader should not try to refresh.  There's `<image>` if you want to an image like a logo to your feed when it shows up in a reader.  You can also add `<webMaster>` for who to contact if there's an issue.

There's more stuff but much of it is not super relevant anymore.

### Items

Items are the actual posts, or stories you want to share.  The are directly beneath the `<channel>` which is a bit odd but here's where you might want a loop or something that generates the items.

Items have a few child elements which are all optional.  The ones you most want are `<title>`, `<link>` and `<pubDate>` which are all pretty self explanatory.  Some readers might even decide to not show items with future `<pubDate>`s.

And that's pretty much it.  Really simple indeed.

## Building the RSS feed

I'm just going to make a new liquid template to use as the feed.  It will roughly follow the link section except sort in forward post order.

I'm also giving it some front-matter to exclude it from other processes and to set the link to `rss.xml`.  I'm not sure if it's better to use `.rss` or `.xml` to be honest.

#### Dates

Dates in RSS are weird.  They use a format that comes from [RFC822](https://www.w3.org/Protocols/rfc822/#z28) which is not in wide circulation anymore. It's also a bit underspecified in general.  All numbers are 2-digit with leading 0s and hours is 24-hour format.

In liquid this would be: `%a, %d %b %Y %H:%M:%S GMT`.

## Implementation

```xml
---
permalink: /rss.xml
eleventyExcludeFromCollections: true
---
<rss version="2.0">
	<channel>
		<title>ndemsic blog</title> 
		<link>https://nl.ndesmic.com</link>
		<description>Ndesmic's blog of programming, video games and other stuff</description>
		<language>en-us</language>
		{% for post in collections.posts %}
			<item>
				<title>{{ post.data.pageTitle }}</title>
				<link>{{ post.url }}</link>
				<pubDate>{{ post.date | date: "%a, %d %b %Y %H:%M:%S GMT" }}</pubDate>
			</item>
		{% endfor %}
	</channel>
</rss>
```

## Testing in a reader

Unfortunately I couldn't find a decent offline reader, everyone wants you to pay a sub in their webapp...sigh.  Feedly seemed to be the most popular so I made a free account, push up my code and pasted in the rss url.  

![Screenshot 2021-09-12 160005](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gxpovu6xpm8s3lf8a5a5.png)

Data seems right.  I didn't add a channel image so it's boring but it works. 

## RSS Optimization

We can optimize some things besides images (I'm far too lazy to make descriptions and images for each post).  One thing we can do is add auto-discovery so that RSS apps pick up our feed when users visit.  This is done via a `<link>` tag:

```html
<link rel="alternate" type="application/rss+xml" 
  title="RSS Feed ndesmic blog" 
  href="/rss.xml" />
```

We just need to add that to our layouts so that reader extensions can detect it.  To test I tried another extension called RSS feed reader.  To be honest I didn't like it as it seemed to have a bug where it always showed the welcome screen but I could at least verify it noticed my feed by the icon.
 
![Screenshot 2021-09-12 165529](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/49iqee5rlbt2kama158d.png)

Each reader will have different things they do to make the experience a bit better.  Feedly for instance uses main images in the article to present it in the feed and has a few markup extensions it looks for for things like branding color.  For instance I added: `<webfeeds:accentColor>000000</webfeeds:accentColor>` so it shows in black.  These will vary so you'll need to really look at the types of apps you are targeting to optimize to them.

The rest gets more into a discussion on branding and content guidelines which are just too taxing for my personal blog.

You can see feedly's recommendations: https://blog.feedly.com/10-ways-to-optimize-your-feed-for-feedly/

---

Anyway, it's good to see that RSS is still somewhat alive and still really easy to implement.  To be honest I was expecting to have to do a little more of a dive, but nope, it's that easy.  It's a little sad the reader front is not great and all about paid subs but as long as we adhere to standards we don't need to do much on our side, just write content and let them worry about how to consume it.  I don't expect most users will go for RSS given how the biggest content silos are incentivized to make content publishers adhere to their own proprietary standards and in app engagement but for 15 minutes of work to let users have the choice to roll their own feed with your content is pretty cool anyway.