Open In App

Real Time News Aggregator with NodeJS and ExpressJS

Last Updated : 22 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will create a real time news application with the help of NodeJS and ExpressJS. This article consists of several main functionalities. First, we will display the news article. Then we have implemented the search functionality to search news based on the title of the news. Then we get the feature to have sorting by date and we can get news of a specific date.

Output Preview: Let us have a look at how the final output will look like.

Screenshot-2024-03-20-102907

Final Output

Pre-requisites:

Approach to create a Real Time News Aggregator:

We will make use of NodeJS, ExpressJS, EJS and Tailwind CSS to develop our Real Time News Aggregator Application. In this project we will implement two important features, one is displaying the news article and then we can further explore more about each particular news by clicking on Read more.

Project Structure:

Screenshot-2024-03-16-100838

Project Folder Structure

Steps to create the Project:

Step 1: Initialize the Project

npm init --yes

Step 2: Install Dependencies

npm install express axios ejs tailwindcss nodemon path

Step 3: Start the server

nodemon server.js

Updated Dependencies:

"dependencies": {
    "axios": "^1.6.8",
    "cors": "^2.8.5",
    "ejs": "^3.1.9",
    "express": "^4.18.3",
    "nodemon": "^3.1.0",
    "path": "^0.12.7",
    "tailwindcss": "^3.4.1"
  }

Example: The below mentioned code implements Real Time News Aggregator with NodeJS and ExpressJS.

HTML
<!-- ../Views/index.ejs !-->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>News Aggregator</title>
    <link
      href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css"
      rel="stylesheet"
    />
  </head>
  <body class="bg-gray-100">
    <div
      class="container mx-auto mt-8 flex flex-col items-center justify-center"
    >
      <form
        action="/search"
        method="GET"
        class="flex items-center justify-center mt-4"
      >
        <input
          class="w-64 px-4 py-2 rounded-l-lg border border-gray-300 focus:outline-none focus:border-blue-500"
          name="search"
          type="search"
          placeholder="Search"
          aria-label="Search"
        />
        <button
          class="px-4 py-2 bg-red-500 text-white rounded-r-lg hover:bg-red-600"
          type="submit"
        >
          Search
        </button>
      </form>

      <form action="/sort-by-date" method="GET">
        <button
          class="mt-4 px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600"
          type="submit"
        >
          Sort by Date
        </button>
      </form>

      <form action="/news-by-date" method="GET" class="mt-4">
        <label for="specific-date" class="block mb-2"
          >Get News for Specific Date:</label
        >
        <input
          id="specific-date"
          class="w-64 px-4 py-2 rounded-lg border border-gray-300 focus:outline-none focus:border-blue-500"
          name="date"
          type="date"
          aria-label="Specific Date"
        />
        <button
          class="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600"
          type="submit"
        >
          Get News
        </button>
      </form>

      <h1 class="text-3xl font-bold my-4 text-center">Latest News</h1>
      <div
        id="news-container"
        class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"
      >
        <% news.forEach(article => { %>
        <div class="article border p-4 bg-white rounded-lg shadow-md">
          <h2 class="text-lg font-bold mb-2"><%= article.title %></h2>
          <p class="text-gray-700"><%= article.description %></p>
          <p class="text-gray-700 article-date">
            Published at: <%= article.publishedAt %>
          </p>
          <a
            href="<%= article.url %>"
            class="text-blue-600 font-semibold mt-2 inline-block"
            >Read more</a
          >
        </div>
        <% }); %>
      </div>
    </div>
  </body>
</html>
JavaScript
// server.js

const express = require("express");
const path = require("path");
const axios = require("axios");

const app = express();

app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");

app.get("/", async (req, res) => {
  try {
    const response = await axios.get(
      "https://newsapi.org/v2/top-headlines?country=in&apiKey=679b913ddb014617bcc93a0bb89ee1ee"
    );
    const data = response.data;

    res.render("index", { news: data.articles });
  } catch (error) {
    console.error("Error fetching news:", error);
    res.status(500).send("Error fetching news. Please try again later.");
  }
});

app.get("/search", async (req, res) => {
  try {
    const searchTerm = req.query.search;
    const response = await axios.get(
      `https://newsapi.org/v2/everything?q=${searchTerm}&apiKey=679b913ddb014617bcc93a0bb89ee1ee`
    );
    const data = response.data.articles;

    const news = data.filter((dataItem) => dataItem.title?.toLowerCase().includes(searchTerm?.toLowerCase()));

    res.render("index", { news });
  } catch (error) {
    console.error("Error fetching search results:", error);
    res
      .status(500)
      .send("Error fetching search results. Please try again later.");
  }
});

app.get("/sort-by-date", async (req, res) => {
  try {
    const response = await axios.get(
      "https://newsapi.org/v2/top-headlines?country=in&apiKey=679b913ddb014617bcc93a0bb89ee1ee"
    );
    const data = response.data.articles;

    data.sort((a, b) => new Date(b.publishedAt) - new Date(a.publishedAt));

    res.render("index", { news: data });
  } catch (error) {
    console.error("Error sorting articles by date:", error);
    res.status(500).send("Error sorting articles by date. Please try again later.");
  }
});

app.get("/news-by-date", async (req, res) => {
  try {
    const date = req.query.date;
    const response = await axios.get(
      `https://newsapi.org/v2/everything?q=*&from=${date}&to=${date}&sortBy=popularity&apiKey=679b913ddb014617bcc93a0bb89ee1ee`
    );
    const data = response.data.articles;

    res.render("index", { news: data });
  } catch (error) {
    console.error("Error fetching news by date:", error);
    res.status(500).send("Error fetching news by date. Please try again later.");
  }
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

Output:

ezgifcom-animated-gif-maker-(5)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads