a quick-start guide on serving your own rss feed

2025-11-09

Setting up an RSS feed took me longer than I thought it would. There wasn't really any good quick start guides on getting a feed going. I had to source multiple articles and then finally run it through an RSS validator. Most searches will lead you to tools that will convert websites into feeds which isn't what I wanted. Instead I wanted to serve the XML file myself with full control over the resulting feed file.

the xml file

<rss version="2.0"
  xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <!-- This should represent the url serving your RSS feed -->
    <atom:link href="http://myawesomeblog/rss.xml" rel="self" type="application/rss+xml" />
    <title>my awesome blog</title>
    <link>
    http://myawesomeblog</link>
    <language>en-us</language>
    <description>
      your blog description
    </description>
    <!-- Optional: Should represent the time the feed was updated -->
    <!-- Also note this is required to be in date format RFC 822 -->
    <lastBuildDate>
      Mon, 10 Nov 2025 05:04:17 +0000
    </lastBuildDate>
    <!-- List of items -->
    <item>
      <!-- At least one of title/description is required -->
      <title>some blog post title</title>
      <description>the body of your post</description>
      <link>
      http://myawesomeblog/some-blog-post-title</link>
      <!-- Optional: RFC 822 date of post publish date -->
      <pubDate>
        Mon, 10 Nov 2025 05:04:17 +0000
      </pubDate>
      <!-- Optional: global id of your item, I used the link -->
      <guid>http://myawesomeblog/some-blog-post-title</guid>
    </item>
  </channel>
</rss>

Even though some fields in here are optional, I recommend having all of them for full compliance. This file is all you need to serve an RSS feed. Below I'll outline the steps I took to render it for my stack but you could technically stop reading here and take the above XML and apply it to your framework.

serving the feed

I'll be using python flask/quart as an example for serving the XML file.

from email import utils
from quart import Quart, render_template

import db

app = Quart(__name__)

@app.route("/rss.xml")
async def feed():
	# get your items
    posts = db.get_posts()
    
    # Use the built-in email utils in python to get an RFC 822 formatted date
    last_build_date = utils.formatdate(
        timeval=datetime.now().astimezone().timestamp(), localtime=True
    )

    return await render_template(
        "rss.xml", posts=posts, last_build_date=last_build_date
    ), {"Content-Type": "application/rss+xml"}

In order to pass RSS validation you must have the Content-Type header set correctly to application/rss+xml some sites will tell you differently but this is the official type.

making it discoverable

Simply add to your html <head></head> the following link:

<head>
	...
	<link rel="alternate"
		  type="application/rss+xml"
		  title="my awesome blog"
		  href="http://myawesomeblog/rss.xml">
	...
</head>

That's all you need to get started.