how to generate an rss feed for your next.js blogsyndicate your content with rss
minute read
Imagine being able to log into one dashboard and getting the latest news and events from all of your favorite websites, blogs, or podcasts?
RSS feeds are what make experiences like that possible. Without them, we’d be forced to check each blog individually for updates. At best, we could subscribe to the blog’s newsletters to stay in the know as new articles are released, but we’d still need to actually read the email, then go to the blog, and then read the article.
To be frank, that sounds awful.
The good news is that RSS feeds (which stands for Really Simple Syndication) have already solved this problem for us. RSS feeds provide a standardized data structure for feed-like updates that can be consumed by popular news aggregator apps like Feedly or Inoreader.
So, the TL;DR is that an RSS feed makes it easy for readers to consume your content. And when blogging, content is the name of the game, so why not make it more accessible?
Not all blogs are created equal
If you’re reading this, you probably have a blog with Next.js already, or you’re considering starting one up. But do you know what's really happening under the hood?
If you fall into the former, in your blog, try appending /feed.xml
to the end of the root domain. If you see some XML pop onto the screen, then you already have an RSS feed set up, and no further action is required. If you see a 404 error at /feed.xml
, follow the steps in the next section to learn how to set one up.
If you fall into the latter group and haven’t started your blog yet, then you can use a template like my Next.js blog starter that comes with an RSS feed baked right in.
Setting up an RSS feed in Next.js
An RSS feed should update automatically anytime you add new content to your blog. To ensure that happens, we’ll create a script to generate the RSS feed, and we’ll configure the package.json
scripts to run it after each build. That way the content of your blog always remains in sync with the RSS feed you’re delivering to your readers.
- Create a new directory at the root of your project called
scripts
- In the new
scripts
directory, create a file calledgenerate-rss.mjs
Wait a second, what the heck is an .mjs
file? The extension simply indicates that the file is an ES6 module, so we can use syntax like import
and export
. Learn more in this StackOverflow post.
We’re going to be using a few different packages in this sitemap, so let’s go ahead and add those imports to the top of the page now.
import { writeFileSync, readFileSync } from 'fs';
import RSS from 'rss';
import { globby } from "globby";
import matter from 'gray-matter'
If you don't have all these currently installed into your project, you can install them as developer dependencies with either command below:
# with yarn
yarn add --dev rss globby grey-matter
# or with npm
npm install --save-dev rss globby grey-matter
Next add an async function, responsible for generating the actual feed.
import { writeFileSync, readFileSync } from 'fs';
import RSS from 'rss';
import { globby } from "globby";
import matter from 'gray-matter'
// Add async function
async function generate() {
}
generate();
Since the RSS feed should contain all our posts, let’s gather all the posts together. In my Next.js starter, the posts are markdown files, and live in the _posts/
directory. Let’s pull those into the function using globby
.
import { writeFileSync, readFileSync } from 'fs';
import RSS from 'rss';
import { globby } from "globby";
import matter from 'gray-matter'
async function generate() {
// Get all posts with globby
const allBlogs = await globby([
'_posts/*.md',
]);
}
generate();
allBlogs
is now an array, packed full of your post’s file names. Perfect! Let’s come back to this. In the meantime, we need to set up the base URLs for the RSS feed.
import { writeFileSync, readFileSync } from 'fs';
import RSS from 'rss';
import { globby } from "globby";
import matter from 'gray-matter'
async function generate() {
const allBlogs = await globby([
'_posts/*.md',
]);
// Set up RSS feed URLs
const feed = new RSS({
title: 'SANDYPOCKETS',
site_url: 'https://sandypockets.dev',
feed_url: 'https://sandypockets.dev/feed.xml'
});
}
generate();
Now for the meat and potatoes of our generate()
function. We’ll:
- Use the file name, and
fs.readFileSync()
to get all the content within each file, including its front matter. - Use
matter
to read the post’s front matter - Use the
.replace()
method to format the file names, trimming the.md
extension - Pass the post as an item to the
feed
object from the RSS feed we created earlier. - Use
fs.writeFileSync()
to output the data intopublic/feed.xml
import { writeFileSync, readFileSync } from 'fs';
import RSS from 'rss';
import { globby } from "globby";
import matter from 'gray-matter'
async function generate() {
const allBlogs = await globby([
'_posts/*.md',
]);
const feed = new RSS({
title: 'SANDYPOCKETS',
site_url: 'https://sandypockets.dev',
feed_url: 'https://sandypockets.dev/feed.xml'
});
// Loop over each post title
allBlogs.map((post) => {
// Read entire contents of each post
const fileContents = readFileSync(post, 'utf8')
// Get front matter from post
const { data } = matter(fileContents)
// Format post URL
const slug = post
.replace('_posts', '/posts')
.replace('.md', '')
// Pass formatted data to RSS feed
feed.item({
title: data.title,
url: `https://sandypockets.dev${slug}`,
date: data.date,
description: data.excerpt
});
});
// Output RSS feed at /feed.xml
writeFileSync('public/feed.xml', feed.xml({ indent: true }));
}
generate();
Configuring your package.json
We’ve created a script, but at the moment we’re not actually calling this file anywhere. Since we want it to run automatically with after each build, we can take advantage of the scripts
in the package.json
file; specifically the postbuild
script. Add the following script to your package.json
file.
"postbuild": "node ./scripts/generate-rss.mjs",
If you want to run a second action on the postbuild
script, you can include it with &&
like this:
"postbuild": "node ./scripts/generate-rss.mjs && node ./scripts/generate-sitemap.mjs",
With that, your package.json
file should look something like this:
{
"name": "blog",
"version": "0.1.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"postbuild": "node ./scripts/generate-rss.mjs",
},
"dependencies": {
Testing
Build your app. That’s it.
- Run
yarn build
- Note the
public/feed.xml
file that has been generated - Run
yarn start
- Navigate to
localhost:3000/feed.xml
to view the XML RSS feed.
Consuming an RSS feed
While an RSS feed is really for your readers, and not something you’ll need to use personally, you might be interested in giving RSS feeds a try for your own news. Inoreader (rated Wired Magazine’s “Best Overall” RSS reader) touts its ability to help you “Take back your news feed”. In a world of noise, that’s a big deal.
If that’s a route you want to go, then you’ll need some sort of app to receive and parse the RSS feed data. Which one is best for you is going to depend on your workflow, but some favourites around the web are the aforementioned Inoreader, Feedly (“Best for Beginners”), or Newsblur (“Best for DIYers”, and compatible with IFTT (If This Then That))
Further reading
- How do RSS feeds work - RSS.com
- RSS - MDN
- Best RSS Feed Readers - Wired.com
- Reading and writing files with JavaScript
Deploy your own blog, with a built-in RSS feed and sitemap using my Next.js blog starter template