Fetching Blog RSS Feeds for Building a GitHub Profile
Tags: github, rss, opengraph
Published: 2023-04-08 14:55:52

---
title: Fetching Blog RSS Feeds for Building a GitHub Profile
published: true
description: Creating a customized user profile page for GitHub to showcase work projects and make navigation to relevant projects and content easier. This is part 3 of 4.
tags: github,rss,opengraph
series: ["GitHub Profile"]
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
---

Introduced in 2020, the GitHub user profile README allow individuals to give a long-form introduction. This multi-part tutorial explains how I setup my own profile to create dynamic content to aid discovery of my projects:

- [with the Liquid template engine and Shields](https://dev.to/j12y/setup-a-dynamic-github-profile-readme-3lbm) (Part 1 of 4)
- [using GitHub's GraphQL API to query dynamic data about all my repos](https://dev.to/j12y/setup-a-dynamic-github-profile-readme-3lbm) (Part 2 of 4)
- **fetching RSS blog post details from third-party sites** (keep reading below)
- [automating updates with GitHub Actions](https://dev.to/j12y/automating-github-profile-updates-with-github-actions-14i3) (Part 4 of 4)

You can visit [github.com/j12y](https://github.com/j12y) to see the final result of what I came up with for my own profile page.

![My GitHub Profile](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hlg6ws0r5hwxel0ii84h.png)

## Display Most Recent Blog Posts

The goal is to create a learning section that is populated by the most recent blog posts or articles from various sources. For example, if I publish a new tutorial like the one you are reading now I would like it to appear on my profile to improve discoverability of new content.

![Learn from recent blog posts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fnfklth1uku753mw5q23.png)

Typically, I publish long-form blog content about what I'm working on in a few specific sites:
✔️ Dev.to
✔️ Medium.com
✔️ Dolby.io

Fortunately, each of these provides either an Atom or RSS feed so that we can subscribe.

## Parsing an RSS Feed for Blog Posts

**Really Simple Syndication** (RSS) has been around for quite some time as a remnant of the popularity behind creating a semantic web by treating web sites themselves like data. Not too long ago I encountered a web developer who was surprised anybody still uses it, but I often use feeds to get new content notifications in Slack and I frequently use [Feedly](https://feedly.com/) as my preferred way of reading the Internet. Technically, there is an alternative spec in **Atom** feeds as well.

Looking around a little bit I found [rss-parser](https://www.npmjs.com/package/rss-parser) which fit my requirements to be lightweight, straightforward to use, and provided sample code that shows how to use it in a TypeScript project.

```typescript
import Parser from 'rss-parser'

parser = new Parser()
const feed = await this.parser.parseURL(url);
for (const item of feed.items) {
  console.log(item.title);
  console.log(item.link);
}
```

The attributes and version of the feed will largely determine the structure of the data and `rss-parser` will allow for the custom fields. The feeds I want to parse are pretty standard so didn't require much customization. 

Similar to the [gallery](https://dev.to/j12y/query-github-repo-topics-using-graphql-35ha) I want the blog posts to display a small image. To do this, I'll need to extract social card data from the website itself.

## Unpacking Open Graph Social Cards

When you include the URL of a website in a social media application like LinkedIn, Twitter, Facebook or into a messaging app like Slack or Discord the link will expand into something more graphically interesting. 

This happens because specific `<meta>` tags have been defined in the `<head>` of the web site.

```html
<meta name="twitter:image:src" content="https://thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png">
<meta property="og:image" content="https://thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png">
```

The description, title, author are all typically included in the RSS feed but the images are not. To solve for this, we can follow the `link` from the RSS feed and fetch the page itself.

Naively, I initially considered using something like axios to fetch the HTML. I could then use a library like jsdom or cheerio to parse it. Fortunately, I found [open-graph-scraper](https://www.npmjs.com/package/open-graph-scraper) which like rss-parser met my technical requirements. Additionally, as part of my evaluation criteria I noted that the project has a reasonable MIT license, a sizable number of weekly downloads, and a repos with the code that has a fair number of stars, watchers, and ongoing maintenance.

```typescript
const ogs = require('open-graph-scraper')

// RSS fetch loop to retrieve each item from the feed

await ogs({url: item.link, ogImageFallback: true})
    .then((data: any) => {
        const { error, result, response } = data;
        image = result.ogImage.url;
        snippet = result.ogDescription;
    });
```

In a few feeds, the `snippet` may be the first x characters from the story itself. In addition to the `meta` image, the `description` is often a succinct summary that is written for SEO purposes and would be more appropriate for the cards.


## Fetch the latest Blog Post and Display

The last piece is not dissimilar to what is described in [how-to use liquid](https://dev.to/j12y/setup-a-dynamic-github-profile-readme-3lbm) template engine. 

We fetch the most latest article from each source. The way the URL for feeds is constructed is a bit esoteric, but you can see the examples below for each of Medium, Dev.to, and Dolby.io.

```typescript
  let feed_url = `https://${process.env.MEDIUM_ID}.medium.com/feed`;
  const medium = await feeds.getRecentArticles(feed_url);
  scope['medium_post'] = medium[0];

  feed_url = `https://dev.to/feed/${process.env.DEVTO_ID}`;
  const devto = await feeds.getRecentArticles(feed_url);
  scope['devto_post'] = devto[0];

  feed_url = `https://dolby.io/blog/author/${process.env.DOLBYIO_ID}/feed/`;
  const dolbyio = await feeds.getRecentArticles(feed_url);
  scope['dolbyio_post'] = dolbyio[0];
```

And we can layout the results in the template. The shield adds a nice little decorator that can link to the full activity feed page while the item details are there to link to the content itself.

```html

<td width="25%" valign="top" style="padding-top: 20px; padding-bottom: 20px; padding-left: 30px; padding-right: 30px;">
  <div align="center"><a href="https://dev.to/@j12y" target="_blank"><img src="https://img.shields.io/badge/dev.to-0A0A0A?style=for-the-badge&logo=devdotto&logoColor=white"/></a></div>
  <img src="{{ devto_post.image }}"/>
  <p><b><a href="{{ devto_post.url }}">{{ devto_post.title }}</a></b></p>
  <p>{{ devto_post.snippet | slice: 0,150 }}...</p>
</td>

```

## Learn more

I hope this overview helps fetch your own learning resources. The next article will dive into how the dynamic components are assembled.

- [Automating GitHub Profile Updates with Actions](https://dev.to/j12y/automating-github-profile-updates-with-github-actions-14i3) (Part 4 of 4)


Did this help you get your own profile started? Let me know and follow to get notified with updates when the next article comes out.