A feed app is a simple app that curates the latest news and articles all over the web and different sources.
So in this article, I will explain how to simply create one using React, Tailwind CSS and my Feed API (https://medrum.herokuapp.com). At the end of this article, we'll be able to build something similar to this - https://ey6n5.csb.app/
If you want a live and hands-on experience, you can follow the video below:
Subscribe to my channel here: https://bit.ly/oyetoketoby
If you are not able to watch the video, you can simply continue reading on below.
Prerequisites
- CRA (react)
- Axios (http)
- Tailwind CSS (CDN) (not necessary)
Setting Up Our Project
The first step here is to set up our react project using Create-React-App. If you don't have it installed, you can read about the installation process here.
To create our app, simply run the command below:
$ npx create-react-app feed-app
After successfully creating our CRA app, let's get into other setups.
Navigate to the src
folder in the main directory and create:
- A
components
folder. Then in thecomponents
folder, create three files (sidebar.js
,main.js
,articles.js
). - a
config.js
file
$ mkdir components
$ touch config.js components/sidebar.js components/main.js components/articles.js
The next thing is to add the Tailwind CSS to your project. There are many ways to do this, but the easiest and fastest way is to use the CDN. You can head over here to get the CDN or simply use the one below:
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
Now in the public
folder, open the index.html
and update it with the Tailwind CSS.
Feed API - Understanding How Medrum API Works
Before we proceed into coding and the next phase of the project, let's try to understand how the Feed API works. Medrum is built using Python, BeautifulSoup, and Scrapy to scrape articles, news and other various things on the internet.
Medrum has two endpoints, articles
and feeds
. In articles, you can't really specify which source you want to read from, but you can from feeds.
Basically, to get latest articles, you can send a request to this endpoint - https://medrum.herokuapp.com/articles/ which would return something like below:
[{"title": "Juno Makes Writing Julia Awesome", "url": "https://towardsdatascience.com/juno-makes-writing-julia-awesome-f3e1baf92ea9", "comment_url": null, "ago": "3h", "date": "2020-02-02 04:06:09AM UTC"}, {"title": "Introducing Leya: The Meta-Statistical Lisp-like language", "url": "https://towardsdatascience.com/introducing-leya-the-meta-statistical-lisp-like-language-ef9012affbdb", "comment_url": null, "ago": "8h", "date": "2020-02-01 11:26:32PM UTC"}, {"title": "Transform Reality with Pandas", "url": "https://towardsdatascience.com/transform-reality-with-pandas-96f061628030", "comment_url": null, "ago": "10h", "date": "2020-02-01 09:34:26PM UTC"}, {"title": "Using Stringr and Regex to Extract Features from Textual, Alphanumeric and Punctuation Data in R", "url": "https://towardsdatascience.com/using-stringr-and-regex-to-extract-features-from-textual-alphanumeric-and-punctuation-data-in-r-2565256c0a77", "comment_url": null, "ago": "13h", "date": "2020-02-01 06:31:13PM UTC"}, {"title": "Getting Browser User Permission with the Permissions API", "url": "https://levelup.gitconnected.com/getting-browser-user-permission-with-the-permissions-api-eafbc9c7f4d7", "comment_url": null, "ago": "15h", "date": "2020-02-01 04:03:06PM UTC"}, {"title": "Get More Out of Google Colab", "url": "https://medium.com/analytics-vidhya/get-more-out-of-google-colab-5bf9d9519a56", "comment_url": null, "ago": "16h", "date": "2020-02-01 03:34:54PM UTC"}]
You can filter the intervals of the articles scraped. It can either be latest
, day
, week
, month
. For instance, you can get all articles posted this week using - https://medrum.herokuapp.com/articles/?interval=week.
To be able to get a feed, you must specify a source id, which can be found here - https://medrum.herokuapp.com/sources/
To get dev.to
feeds, you'd need to use the dev.to source id (5bbb1af8af62ff6841b4b26e
) in the combination below:
https://medrum.herokuapp.com/feeds/?source=5bbb1af8af62ff6841b4b26e&page=1&sort=popular
You can filter the endpoints using page
and sort
(popular
, latest
).
Cool right and it's free to use.
You can support me on Patreon - https://www.patreon.com/oyetoketoby to continue building free APIs
Building Our Feed Application
Now that we have understood how the API works, let's see how to incorporate this into our app.
Open the config.js
file:
export const SOURCES_URL = "https://medrum.herokuapp.com/sources/"
export const FEEDS_URL = "https://medrum.herokuapp.com/feeds"
This contains the two endpoints we'll be using in our application.
Now open the main.js
file and paste the below:
import React, { useState, useEffect } from "react";
import Sidebar from "./sidebar";
import Articles from "./articles";
import { SOURCES_URL, FEEDS_URL } from "../config";
import axios from "axios";
function Main() {
const [sources, setSources] = useState([]);
const [articles, setArticles] = useState([]);
const [source, setSource] = useState([]);
const fetchSource = id => {
setSource(id);
setArticles([]);
axios.get(`${FEEDS_URL}?source=${id}`).then(res => {
setArticles(res.data);
});
};
useEffect(() => {
axios.get(SOURCES_URL).then(res => {
setSources(res.data);
});
fetchSource("5718e53d7a84fb1901e05914");
}, []);
return (
<div className="flex">
<div className="w-1/4 bg-gray-500 p-3">
<Sidebar source={source} sources={sources} fetchSource={fetchSource} />
</div>
<div className="w-3/4 bg-gray-400 p-3">
<Articles articles={articles} />
</div>
</div>
);
}
export default Main;
Here's what we did above:
- We imported our
Sidebar
andArticles
components - We added three
useState
hooks -sources
,articles
,source
- We created a function-
fetchSource
: This will be used in getting a source feeds. - We added a
useEffect
hooks: This will get the available sources we can get their feeds and also loads a source feed by default. - We passed the
source
,sources
andfetchSource
to theSidebar
component andarticles
to theArticles
components as props
The next thing is to open the sidebar.js
component:
import React from "react";
function Sidebar({ sources, fetchSource, source }) {
if (!sources.length) return <p>Loading...</p>
return (
<>
{sources.map((s, k) => {
if (s.contentType!=="news") return null;
return (
<p
key={k}
className="mb-3"
style={{background: s.id===source ? "#ccc": "transparent"}}
onClick={() => {
fetchSource(s.id);
}}
>
{s.name}
</p>
);
})}
</>
);
}
export default Sidebar;
The above is actually very easy to understand, but here's the breakdown:
- Show loading if the
sources
prop is empty - Map through the
sources
prop, check if the contentType of the current source is news, then display the name, add an onClick event to callfetchSource
with the source id as param and add a background if the current source id is the active source id.
The next thing now is to open the articles.js
file:
import React from "react";
function Articles({ articles }) {
if (!articles.length) return <p>Loading...</p>
return (
<>
{articles.map((a, k) => {
return (
<p className="mb-4" key={k}>
<a href={a.url} target="_blank">{a.title}</a>
</p>
);
})}
</>
);
}
export default Articles;
In this we didn't do anything much, we only mapped through the articles
prop to display all the feeds.
The last thing to do is to import our main.js
component in app.js
file:
import React from "react";
import "./styles.css";
import Main from "./components/main";
function App() {
return (
<div className="wrapper">
<Main/>
</div>
);
}
That's it! If everything goes well, you should see something like below:
That's all. You can check out a live demo here: https://ey6n5.csb.app/. You can check out the code on code sandbox here: https://codesandbox.io/s/boring-moore-ey6n5
Don't forget to share to others and if you want to support me here's my Patreon: https://www.patreon.com/oyetoketoby