list of publications, books, shelve
Photo by Karim Ghantous on Unsplash

Vanity fair — how to display the list of your Medium publications

D o you have a personal website? Or maybe you are thinking about getting one? Wouldn’t it be nice to have a “vanity section” with a list of all your publications scattered around the Internet? This article describes the way you can list your Medium stories with Angular using the RSS feed.

[TL;DR: No authentication needed, use ‘https://api.rss2json.com/v1/api.json? rss_url=https://medium.com/feed/@YOUR_MEDIUM_USERNAME’ to avoid CORS issues for localhost development and rss-to-json parsing]

First of all, Medium provides some OAuth2 APIs. Check out this documentation. The good news is though, that you don’t need any authentication if you just need a list of publications of a particular user. As mentioned in this discussion, the Medium OAuth2 APIs are for writing purposes (and for some advanced user information). The listPublications scope of the OAuth2 API does not return the stories of the user, but grants the ability to list publications related to him/her.

The magic URL that you can use to get your stories is https://medium.com/feed/@your_profile

My very basic implementation includes the following steps.

1. Define the class Publication

export class Publication{
constructor(public title: string, public url: string){};
}

This is the basic elements that I want to display. You might also want to add you profile picture or the publication data.

2. Create the PublicationService

import { Publication } from ‘./publication.module’;
import { HttpClient } from ‘@angular/common/http’;
import { Injectable } from ‘@angular/core’;
@Injectable({ providedIn: ‘root’, })
export class PublicationService {
constructor(private http: HttpClient) {}
getMediumPublications(url: string){
return this.http.get(url);
}
}

Don’t forget to import HttpClientModule from ‘@angular/common/http’ in your app.module. In the component itself, however, we use HttpClient. I want to keep the service as generic as possible because later on I’m going to use it for LinkedIn and further publications, too. Hence, all the Medium specific topics will be places in the component.

3. Create MediumPublicationsComponent

import { Component, OnInit } from '@angular/core';
import { PublicationService } from '../publications.service';
import { Publication } from '..//publication.module';
@Component({
selector: 'app-medium-publications',
templateUrl: './medium-publications.component.html',
styleUrls: ['./medium-publications.component.scss']
})
export class MediumPublicationsComponent implements OnInit {
isFetchingPosts = false;
httpErrorOccured = '';
private mediumUser = 'YOUR_MEDIUM_USERNAME';
private mediumUrl = 'https://medium.com/feed/@' + this.mediumUser;
constructor(public publicationService: PublicationService) { }
ngOnInit() {
this.isFetchingPosts = true;
this.publicationService.getMediumPublications(this.mediumUrl)
//.pipe(parse RSS to JSON here)
.subscribe((data) => {
if (data.hasOwnProperty('items')){
data.items.forEach( (element) => {
this.mediumPublications
.push(new Publication(element.title, element.link));
});
}
this.isFetchingPosts = false;
}, error =>{
this.httpErrorOccured = error.message;
});
}
}

This component sends an http request to Medium feed via the PublicationService that we created above. It gets the response and pushes the publications to the array of Publications that we need for our *ngFor later on. isFetchingPosts is used to display a loading icon before the results can be displayed. httpErrorOccured is used to display an error message in case our http request fails. Feel free to add typing for the response data and property modifiers.

Well, that would be too easy if it worked just like that.

error message display, cors
Taken from here

Issue №1: If you check out the link https://medium.com/feed/@YOUR_MEDIUM_USERNAME, you would notice that the response is not JSON but RSS which is a dialect of XML. So you need to pipe() it with some additional libraries like rss-to-json.

Issue №2: Even if you successfully integrate rss-to-json and try to serve your app locally to see the results… there will be little you can see. Why so? Our old friend, CORS a.k.a. Cross Origin Resource Sharing kicks in and there is little we can do about it on our site.

But this article wouldn’t be there if I gave up at this point. With the following link both problems seem to be solved (at least for the local development):

private mediumUrl = 'https://api.rss2json.com/v1/api.json?   rss_url=https://medium.com/feed/@YOUR_MEDIUM_USERNAME';

You can find more information on the API here. As of now, it seems to be a valid alternative to me.

4. Hook up your html

<div *ngFor=”let publication of mediumPublications”>  <a *ngIf=”mediumPublications.length > 0 && !isFetching
href=”{{publication.url}}”>
{{publication.title}}
</a>
</div><p *ngIf=”mediumPublications.length <= 0 && !isFetching”>
There is no stories published on Medium (yet)
</p>
<p *ngIf=”isFetching && !httpErrorOccured”>Loading…</p><p *ngIf=”httpErrorOccured.length>0">{{httpErrorOccured}}</p>

We iterate through our array of publications, display the titles and link them to the URL of your story. Additionally, we…

  • display a loading sign when the publications are being fetched,
  • inform our user if we finished loading and there is still no publications.
  • inform the user if an error occurred.
stay tuned
Credits here

This is a living document, so stay tuned! I want to add fetching of LinkedIn articles and different styling for the list of my publications next.

[Disclaimer: you think the author misses the point or provides incorrect information? Blame the author AND provide missing / relevant / correct information in your comments — help other readers (and the author) to get it straight! a.k.a. #learningbysharing]

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Maria Korneeva

Maria Korneeva

Learning tech hacks by sharing them with you— that is what drives me. #learningbysharing