RSS isn't dead. Developers still use feed readers, and having a proper /rss.xml or /blog/rss URL is a small but meaningful signal that your site is a real publication. My portfolio runs on a split stack — a React SPA on Vercel and a Django REST API on a separate domain — so adding RSS turned out to be more interesting than I expected. Here's exactly what I built, the bugs I hit along the way, and the final result.
The Setup
-
Frontend: React + Vite, deployed on Vercel at
vicentereyes.org -
Backend: Django (cookiecutter-django), deployed at
backend.vicentereyes.org -
Goal: RSS feed available at two URLs:
-
vicentereyes.org/rss.xml— the classic URL people expect -
vicentereyes.org/blog/rss— the canonical feed linked from the blog page
-
The Django Feed
Django ships with a syndication framework that makes building RSS feeds straightforward. I created blogs/feeds.py:
from io import StringIO
from django.contrib.syndication.views import Feed
from django.utils.feedgenerator import Rss201rev2Feed
from .models import BlogPost
_SITE = "https://www.vicentereyes.org"
_FEED_URL = f"{_SITE}/blog/rss"
_XSL_URL = f"{_SITE}/rss.xsl"
class StyledRssFeed(Rss201rev2Feed):
def write(self, outfile, encoding):
buf = StringIO()
super().write(buf, encoding)
xml = buf.getvalue()
# Insert XSL PI after the <?xml ...?> declaration line
split = xml.index("\n") + 1
outfile.write(xml[:split])
outfile.write(f'<?xml-stylesheet type="text/xsl" href="{_XSL_URL}"?>\n')
outfile.write(xml[split:])
class LatestBlogPostsFeed(Feed):
feed_type = StyledRssFeed
title = "Vicente Reyes - Blog"
link = f"{_SITE}/blog"
description = "Latest posts from Vicente Reyes"
def feed_url(self):
return _FEED_URL
def items(self):
return BlogPost.objects.order_by("-date_published")
def item_title(self, item):
return item.title
def item_description(self, item):
return item.brief
def item_link(self, item):
return f"{_SITE}/blog/{item.slug}-{item.uid}"
def item_pubdate(self, item):
return item.date_published
def item_author_name(self, item):
return item.author_name
Top comments (0)