# Generating RSS Feed with feed - Modern Next.js Blog Series #19

- Canonical: https://easonchang.com/posts/rss-feed
- Date: 2022-10-04T00:00:00.000Z
- Language: en
- Description: Add RSS Feed functionality to the blog, allowing readers to subscribe to new articles via RSS

> This article is also published at [it 邦幫忙 2022 iThome Ironman Contest](https://ithelp.ithome.com.tw/articles/10304162)

## TL;DR

This is the 19th article in the "Modern Blog 30 Days" series. In the previous article, we completed generating a Sitemap. Continuing with a very similar task, this article focuses on generating an RSS Feed, allowing the blog to be subscribed to via RSS.

The code changes for this article are as follows:

https://github.com/eason-dev/nextjs-tailwind-contentlayer-blog-starter/compare/day18-sitemap...day19-rss-feed

---

## Adding an RSS Feed

Install the [feed](https://github.com/jpmonette/feed) package:

```shell
pnpm add feed
```

Modify `src/configs/siteConfigs.ts` by adding credit and email:

```ts
// ...
export const siteConfigs = {
  // ...
  credit: "Stark Industries",
  email: "stark@example.com",
};
```

Add `src/lib/generateRSS.ts`:

```ts
import { Feed } from "feed";
import { writeFileSync } from "fs";

import { siteConfigs } from "@/configs/siteConfigs";
import { allPostsNewToOld } from "@/lib/contentLayerAdapter";
import { getPostOGImage } from "@/lib/getPostOGImage";

export default function generateRSS() {
  const author = {
    name: siteConfigs.author,
    email: siteConfigs.email,
    link: siteConfigs.fqdn,
  };

  const feed = new Feed({
    title: siteConfigs.title,
    description: siteConfigs.description,
    id: siteConfigs.fqdn,
    link: siteConfigs.fqdn,
    image: siteConfigs.logoUrl,
    favicon: siteConfigs.logoUrl,
    copyright: `Copyright © 2015 - ${new Date().getFullYear()} ${
      siteConfigs.credit
    }`,
    feedLinks: {
      rss2: `${siteConfigs.fqdn}/feed.xml`,
      json: `${siteConfigs.fqdn}/feed.json`,
      atom: `${siteConfigs.fqdn}/atom.xml`,
    },
    author: author,
  });

  allPostsNewToOld.forEach((post) => {
    feed.addItem({
      id: siteConfigs.fqdn + post.path,
      title: post.title,
      link: siteConfigs.fqdn + post.path,
      description: post.description,
      image: getPostOGImage(post.socialImage),
      author: [author],
      contributor: [author],
      date: new Date(post.date),
      // content: post.body.html,
    });
  });

  writeFileSync("./public/feed.xml", feed.rss2());
  writeFileSync("./public/atom.xml", feed.atom1());
  writeFileSync("./public/feed.json", feed.json1());
}
```

Modify `src/pages/index.tsx` by adding the above `generateRSS()` function into `getStaticProps` so it executes during `pnpm build` to generate RSS files:

```tsx
// ...
// Add this line to import
import generateRSS from "@/lib/generateRSS";

// ...

export const getStaticProps: GetStaticProps<Props> = () => {
  // ...

  // Add the line below
  generateRSS();

  return { props: { posts } };
};
// ...
```

Modify `src/pages/_app.tsx` to add meta data indicating the path of the RSS Feed throughout the site:

```tsx
// ...
function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ThemeProvider attribute="class">
      <DefaultSeo
        // ...
        additionalLinkTags={[
          {
            rel: "icon",
            href: siteConfigs.logoPath,
          },
          // Add the two link tags below
          {
            rel: "alternate",
            type: "application/rss+xml",
            href: "/feed.xml",
          },
          {
            rel: "alternate",
            type: "application/atom+xml",
            href: "/atom.xml",
          },
        ]}
      />

      <LayoutWrapper>
        <Component {...pageProps} />
      </LayoutWrapper>
    </ThemeProvider>
  );
}

export default MyApp;
```

Modify `.gitignore`, `.eslintignore`, `.prettierignore` to ignore the generated RSS Feed files:

```
# ...
# Add the following 3 rules
# RSS related files (generated by generateRSS.js)
/public/atom.xml
/public

/feed.xml
/public/feed.json
```

## Results

Done! After running `pnpm build`, you'll see `atom.xml`, `feed.json`, and `feed.xml` added to the /public path, providing three different RSS formats.

The generated content includes:

`public/atom.xml`:

(Example XML content for atom.xml)

`public/feed.json`:

(Example JSON content for feed.json)

`public/feed.xml`:

(Example XML content for feed.xml)

The code changes for this article are as follows:

https://github.com/eason-dev/nextjs-tailwind-contentlayer-blog-starter/compare/day18-sitemap...day19-rss-feed

## References

- [jpmonette/feed: A RSS, Atom, and JSON Feed generator for Node.js, making content syndication simple and intuitive! ?](https://github.com/jpmonette/feed)
- [Generate RSS feeds for your static Next.js blog | Phiilu | Florian Kapfenberger](https://phiilu.com/generate-rss-feeds-for-your-static-next-js-blog)
- [Generate RSS feed for Next.js static site - kpman | code](https://code.kpman.cc/2021/05/25/next-js-rss/)

## Next Article

Congratulations on completing the RSS Feed generation!

By now, the blog has all the necessary features to go live.

However, with 11 days still to go, we're not stopping here. In the next 11 days, we'll continue adding more dazzling features, progressing towards the Modern Blog.

In the next article, we'll modify the in-text heading styles and add anchor links to each heading!
