The best news PWA just got better !!
Tags: showdev, javascript, pwa, webdev
Published: 2020-04-06 16:32:27

---
title: The best news PWA just got better !!
published: true
description: My news PWA got improved with new features!!
tags: showdev , javascript , PWA , webdev
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/gbrtafj1aujitsnmd34z.png
---

#### What is Headliner ?
It's a progressive web app(PWA) which collects news articles from API and RSS Feeds. [visit Headliner](https://headliner.cf). The category pages are RSS news aggregators that collect and show news articles from various news providers.
#### How it does what it does?
##### Headliner>
It uses the javascript **fetch()** API to get information from an API endpoint. It makes async requests instead of using the traditional XMLHttp request. The information from the API gets transformed into a **JSON** object. As the news articles come as a js array it's easy to map them to HTML elements using js array method **map()**. 
```
fetch(url)
      .then(resp => resp.json()) // Transform the data into json
      .then(function (data) {
        let news = data.articles;
        return news.map(item => {
          let li = createNode("li"),
              h4 = createNode("h3");
              p2 = createNode("p");
              img = createNode("img");
              link = createNode("a");
              line = createNode("span");
              link2 = createNode("a")
              link3 = createNode("a")

```
The mapped elements with the information get injected into the browser DOM using the javascript DOM API **CreateElement()** to create the elements and **appendChild()** to append them to Browser DOM. It's done by two js functions:
```
function createNode(element) {
          return document.createElement(element); // Create the type of element you pass in the parameters
        }

 function append(parent, el) {
          return parent.appendChild(el); // Append the second parameter(element) to the first one
        }

```
#### Category Pages>
Category pages use [Feddnami](https://github.com/sekando/feednami-client) A lightweight Javascript client for downloading RSS/Atom feeds. After downloading the RSS feeds it uses the same method as headliner to create and append elements to browser DOM. :sunglasses:.
```
feednami.load(url, function(result) {
          if (result.error) {
            console.log(result.error);
          } else {
            var entries = result.feed.entries;
            for (var i = 0; i < entries.length; i++) {
              var entry = entries[i];
              console.dir(entry);
              return entries.map(entry => {
                console.log(entry.link)
```
###Features:

####News Categories :newspaper:
Headliner has news articles categorized in 3 main streams. Which are General News, Technology, and Lifestyle. This solution makes the user experience smooth by eliminating the dilemma of choosing from a plethora of categories. In each of the main category pages, there is an explore option in the feature menu to read articles from other news providers.

####Blazing fast load time :rocket:
With 2s :sunglasses: of loading time as evaluated on Lighthouse, headliner loads blazing fast. In very slow networks or when the device is offline, it shows an offline page using the PWA service worker. 

![Lighthouse Test](https://dev-to-uploads.s3.amazonaws.com/i/gfcakyzxpd5a93ks0g7g.png)

#### PWA :fire: :rocket:
According to the PWA standards, this uses the **manifest.json** and **serviceworker**. The service worker gets installed on load and the custom add to home screen prompt is shown 
```
 //the code for custom add to home screen prompt
  var deferredPrompt;

  window.addEventListener("beforeinstallprompt", function (e) {
    // Prevent Chrome 67 and earlier from automatically showing the prompt
    e.preventDefault();
    // Stash the event so it can be triggered later.
    deferredPrompt = e;

    showAddToHomeScreen();
  });

  function showAddToHomeScreen() {
    var a2hsBtn = document.querySelector(".ad2hs-prompt");

    a2hsBtn.style.display = "block";

    document.getElementById("add").addEventListener("click", addToHomeScreen);
  }
  function addToHomeScreen() {
    var a2hsBtn = document.querySelector(".ad2hs-prompt"); // hide our user interface that shows our A2HS button
    a2hsBtn.style.display = "none"; // Show the prompt
    deferredPrompt.prompt(); // Wait for the user to respond to the prompt
    deferredPrompt.userChoice.then(function (choiceResult) {
      if (choiceResult.outcome === "accepted") {
        console.log("User accepted the A2HS prompt");
      } else {
        a2hsBtn.style.display = "none"; // Show the prompt

        console.log("User dismissed the A2HS prompt");
      }

      deferredPrompt = null;
    });
  }
```
Accepting which will let users install it as a PWA. Headiner also runs offline. It shows an **offline.html** page when the internet is shut off.
#### Dark Mode :fire:
Yes, Headliner has it's own dedicated dark mode. By one toggle at the top it switches to dark mode for better reading comfort.
```
 const body = document.body;
  function dToggle() {
    body.classList.toggle("darkmode");
  }
```
#### Social Sharing :speech_balloon:
Headliner also lets users to share articles on various social networking platforms like whatsapp, facebook etc. It uses the web API **navigator.share()** which invokes the native sharing dialouge. 
```
if (navigator.share) {
navigator.share(
{title:'" + entry.title + "',
text:'shared from Headliner',
url: '" + entry.url + "',
}).then(() =>
console.log('Successful share')).catch((error) => 
console.log('Error sharing', error));}
```

### Thank You.
[Headliner](https://headliner.cf) is developed as a hobby project of mine. This is not monetized or commercialized as all the news articles are the sole property of their providers. This as an Open Source project and I'm inviting all to suggest and contribute to the app.  Feel free to fork the [Github Repo](https://github.com/soulsam480/headliner) :smile: :v:. for any help or suggestions drop a [mail](mailto:soulsam480@gmail.com).