<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: saurabharch</title>
    <description>The latest articles on DEV Community by saurabharch (@saurabharch).</description>
    <link>https://dev.to/saurabharch</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F104082%2Fba4fca7b-131f-4eaf-85be-f57bafa633ce.JPG</url>
      <title>DEV Community: saurabharch</title>
      <link>https://dev.to/saurabharch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/saurabharch"/>
    <language>en</language>
    <item>
      <title>Web Push Notification Full Stack Application With Node Js Restful API</title>
      <dc:creator>saurabharch</dc:creator>
      <pubDate>Tue, 25 Sep 2018 08:24:18 +0000</pubDate>
      <link>https://dev.to/saurabharch/web-push-notification-full-stack-application-with-node-js-restful-api-10i2</link>
      <guid>https://dev.to/saurabharch/web-push-notification-full-stack-application-with-node-js-restful-api-10i2</guid>
      <description>

&lt;p&gt;Let me tell you first, why &lt;strong&gt;Web Push Notification&lt;/strong&gt; is essential for any web application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's helps in broadcasting short messages to the subscriber of the web application and as well as help to support in user engagement with your application to notify the every subscribers, It is really hard to any organisation send email notification for a short messaging event loop or broadcast messages like offers and updates of short messages and it also increases the cost of server operations so the solution is &lt;strong&gt;Web Push Notification&lt;/strong&gt; .it help your the maximum post reachability and getting more consumer engagement on web application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;let me tell you how it's works.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--076-ea75--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/3iE3ihH2TLqI64zeNDsF" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--076-ea75--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/3iE3ihH2TLqI64zeNDsF" alt="web-push-how-working.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;service worker is main key ingrediant and knight of this feature which install in client broswer and run indenpendently as application after intalling in browser as service worker which regularly a send a query to the provider server and ask for any new event happening and than respond to the client if any new event is happening in the server it popup a message like&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VOp4VxXt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/632p2e4RROJCAUPdGPKg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VOp4VxXt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/632p2e4RROJCAUPdGPKg" alt="popup-notify.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;click on allow button service worker start to install in client browser and send a promise request for subscriber with &lt;strong&gt;Public VAPID key&lt;/strong&gt; and check on server for whether user is already subscribe notification or not if it's already subscribe it sent back request with false statement otherwise server sent a true request.&lt;br&gt;
and done that's it.&lt;br&gt;
Now let's Comes to the Coding section and how to implement this feature in your application without using third party paid services and use as long as you.&lt;/p&gt;

&lt;h2&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;Need Prequest which are listed below if you don't have in your System.&lt;br&gt;
&lt;strong&gt;Prequiests:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;IDE &lt;a href="https://visualstudio.microsoft.com/"&gt;Visual Studio Code&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/download/"&gt;Nodejs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://git-scm.com/"&gt;Git&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mongodb.com/download-center?jmp=nav#charts"&gt;MongoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.getpostman.com/apps"&gt;Postman&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now Let's Beigin with next Step&lt;/p&gt;

&lt;p&gt;## &lt;strong&gt;Step 2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;open your IDE &lt;a href="https://visualstudio.microsoft.com/"&gt;Visual Studio Code&lt;/a&gt;&lt;br&gt;
 and than run command in integrated terminal with your IDE&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;than add the all fields or skip as you want&lt;br&gt;
and than run command again to intall all the dependacy with&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install express web-push body-parser mongoose q --save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uj4E3tyh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/GPPnJskQTGhfljoNHSEn" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uj4E3tyh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/GPPnJskQTGhfljoNHSEn" alt="git-init-commands.png"&gt;&lt;/a&gt;&lt;br&gt;
and hit the Enter and wait for install all the dependency will install correclty in your project  than run again run command for creat new application running file&lt;br&gt;
in same project folder by&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch server.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--btxUqdKv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/Vp8V4BfDQV67JLwYgoCD" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--btxUqdKv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/Vp8V4BfDQV67JLwYgoCD" alt="add-new-file-app.png"&gt;&lt;/a&gt;&lt;br&gt;
and again need to create three folders in same project directory by commands as below&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir config
cd config 
touch keys.js
touch keys_prod.js
touch keys_dev.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sn8bNkLj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/fgYHnCfRAWCT59r8yR2f" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sn8bNkLj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/fgYHnCfRAWCT59r8yR2f" alt="creat-config-dir.png"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir model
cd model
touch subscribers_model.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--STtqUdui--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/zcdVJawpQ1udam8tvJE7" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--STtqUdui--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/zcdVJawpQ1udam8tvJE7" alt="creat-model-dir.png"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir router
cd router
touch push.js
touch subscriber.js
touch index.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5rikMKYP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/Za6RRQStQMqtqALHMkto" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5rikMKYP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/Za6RRQStQMqtqALHMkto" alt="creat-router-dir.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;now all the essential folders and file are created and in this project we move to next coding parts in next step.&lt;/p&gt;

&lt;p&gt;## &lt;strong&gt;Step 3&lt;/strong&gt;&lt;br&gt;
 The file structure of this project is as below&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|
|
|________________________./config
|                         |
|                         |____keys_prod.js
|                         |____keys_dev.js
|                         |____keys.js
|
|________________________./public
|                         |
|                         |____index.html
|                         |____sw.js
|                         |____app.js
|
|________________________./model
|                         |
|                         |____subscribers_model.js
|
|________________________./router
|                         |
|                         |____push.js
|                         |____subscribe.js
|
|___________________________server.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;now start with create database model for mongodb database. so now i am using &lt;strong&gt;Mongoose&lt;/strong&gt; ODM ORM library for &lt;strong&gt;MongoDB&lt;/strong&gt; which is already installed in project&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const SubscriberSchema = new Schema({
    endpoint: String,
    keys: Schema.Types.Mixed,
    createDate: {
        type: Date,
        default: Date.now
    }
});

mongoose.model('subscribers', SubscriberSchema, 'subscribers');
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;so now let's come to the config file &lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and than open the keys.js file which is already created in this folder&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (process.env.NODE_ENV === 'production') {
    module.exports = require('./keys_prod');
} else {
    module.exports = require('./keys_dev');
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and update your keys.js file with this code , actually this code provide smart switch database authentication address between production and development application.&lt;br&gt;
Before update the keys_prod.js and keys_dev.js file generate the VAPID keys for client device browser and between the server running application.&lt;br&gt;
by using this command&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./node_modules/.bin/web-push generate-vapid-keys
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;you will see a two keys are generated one is private and another one is public key&lt;br&gt;
 which is show in below.&lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ItM2WagN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/Dw6GP2JWQhuPne1Iu074" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ItM2WagN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/Dw6GP2JWQhuPne1Iu074" alt="create-vapid-key.png"&gt;&lt;/a&gt;&lt;br&gt;
 copy both the keys and paste in to the keys_dev.js or on production enviroment server config.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
//i used mlab database for fast and realiable pace development enviroment
    mongoURI: 'mongodb://web-push:webpush123@ds213053.mlab.com:13053/web-push',
    privateKey: 'ayTIBl3f0gcI-koFq-ZXPxSR4qicC0GcMNHA1dpHaj0' || process.env.VAPID_PRIVATE_KEY,
    publicKey: 'BK3Q7j8fcGFws03RiU5XakzDJ7KGEiRhdIX2H5U8eNmhhkdHT_j0_SD09KL96aFZOH_bsjr3uRuQPTd77SRP3DI' || process.env.VAPID_PUBLIC_KEY
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;process.env.VAPID_PUBLIC_KEY&lt;/strong&gt; or &lt;strong&gt;process.env.VAPID_PRIVATE_KEY&lt;/strong&gt; understand as production server running environment configuration.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Please Make sure you always use or generate your own VAPID keys for your application for more secure your application and make sure your private keys is not expose on the web.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;so now all the important application structure setting is done now start coding in &lt;strong&gt;server.js&lt;/strong&gt; which is exist on top of the project folder&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const path = require('path');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');

require('./model/subscribers_model');

// Load Routes
const index = require('./router');

// subscriber route load push
const push = require('./router/push');

// subscriber route load
const subscribe = require('./router/subscribe');
// Load Keys
const keys = require('./config/keys');
//Handlebars Helpers

mongoose.Promise = global.Promise;

// Mongoose Connect
mongoose.connect(keys.mongoURI, {
        useMongoClient: true
    })
    .then(() =&amp;gt; console.log('MongoDB Connected'))
    .catch(err =&amp;gt; console.log(err));

//Create Express middleware
const app = express();
app.set('trust proxy', true);
// parse application/json
app.use(bodyParser.json());
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
    extended: true
}));

// Set static folder
app.use(express.static(path.join(__dirname, 'public')));
// app.set('views', __dirname + '/public/js');

// Set global vars
app.use((req, res, next) =&amp;gt; {
    res.locals.user = req.user || null;
    next();
});



// Use Routes

app.use('/', index);
app.use('/subscribe', subscribe);
app.use('/push', push);


// catch 404 and forward to error handler
app.use(function (req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function (err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});


const port = process.env.PORT || 3000;

app.listen(port, () =&amp;gt; {
    console.log(`Server started on port ${port}`);
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and now come to the folder &lt;strong&gt;router&lt;/strong&gt; first start with subscribe.js which is already created by command. open this file in new tab and than paste this code in your &lt;strong&gt;subscribe.js&lt;/strong&gt; file&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Subscription = mongoose.model('subscribers');

//Post route of subscribe url is as http://host:3000/subscribe
router.post('/', (req, res) =&amp;gt; {
    const subscriptionModel = new Subscription(req.body);
    subscriptionModel.save((err, subscription) =&amp;gt; {
        if (err) {
            console.error(`Error occurred while saving subscription. Err: ${err}`);
            res.status(500).json({
                error: 'Technical error occurred'
            });
        } else {
            res.json({
                data: 'Subscription saved.'
            });
        }
    });
});

// fixed the error get request for this route with a meaningful callback
router.get('/', (req, res) =&amp;gt; {
            res.json({
                data: 'Invalid Request Bad'
            });
});
module.exports = router;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;save the changes and move to next file &lt;strong&gt;push.js&lt;/strong&gt; and paste this code in your already created &lt;strong&gt;push.js&lt;/strong&gt; file by command line&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Subscription = mongoose.model('subscribers');
const q = require('q');
const webPush = require('web-push');
const keys = require('./../config/keys');
//Post route of push url is as http://host:3000/push
router.post('/', (req, res) =&amp;gt; {
    const payload = {
        title: req.body.title,
        message: req.body.message,
        url: req.body.url,
        ttl: req.body.ttl,
        icon: req.body.icon,
        image: req.body.image,
        badge: req.body.badge,
        tag: req.body.tag
    };

    Subscription.find({}, (err, subscriptions) =&amp;gt; {
        if (err) {
            console.error(`Error occurred while getting subscriptions`);
            res.status(500).json({
                error: 'Technical error occurred'
            });
        } else {
            let parallelSubscriptionCalls = subscriptions.map((subscription) =&amp;gt; {
                return new Promise((resolve, reject) =&amp;gt; {
                    const pushSubscription = {
                        endpoint: subscription.endpoint,
                        keys: {
                            p256dh: subscription.keys.p256dh,
                            auth: subscription.keys.auth
                        }
                    };

                    const pushPayload = JSON.stringify(payload);
                    const pushOptions = {
                        vapidDetails: {
                            subject: "http://example.com",
                            privateKey: keys.privateKey,
                            publicKey: keys.publicKey
                        },
                        TTL: payload.ttl,
                        headers: {}
                    };
                    webPush.sendNotification(
                        pushSubscription,
                        pushPayload,
                        pushOptions
                    ).then((value) =&amp;gt; {
                        resolve({
                            status: true,
                            endpoint: subscription.endpoint,
                            data: value
                        });
                    }).catch((err) =&amp;gt; {
                        reject({
                            status: false,
                            endpoint: subscription.endpoint,
                            data: err
                        });
                    });
                });
            });
            q.allSettled(parallelSubscriptionCalls).then((pushResults) =&amp;gt; {
                console.info(pushResults);
            });
            res.json({
                data: 'Push triggered'
            });
        }
    });
});

// fixed the error get request for this route with a meaningful callback
router.get('/', (req, res) =&amp;gt; {
    res.json({
        data: 'Invalid Request Bad'
    });
});
module.exports = router;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;again make sure save this code changes in your &lt;strong&gt;push.js&lt;/strong&gt; file with this code now again move to the &lt;strong&gt;index.js&lt;/strong&gt; file and update the code with this below code&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const router = express.Router();

router.get('/', (req, res) =&amp;gt; {
    res.locals.metaTags = {
        title: 'web-push-api',
        description: 'Web Push Notification Full Stack Application With Node Js Restful API',
        keywords: 'Web Push Notification Full Stack Application With Node Js Restful API',
        generator: '0.0.0.1',
        author: 'Saurabh Kashyap'
    };
    res.json({
        status: 'ok',
        message: 'Server is running'
    });
});

module.exports = router;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and save the changes in server.js file with above code in &lt;strong&gt;server.js&lt;/strong&gt; file and run command hit this run command&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node server.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;please make sure you will see these messages after hitting this command.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vRIdlUeT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/Cr52K8NiQPOXAv6jOHSe" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vRIdlUeT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/Cr52K8NiQPOXAv6jOHSe" alt="server-running-command.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;press again close the application after checking your application is running correct.&lt;br&gt;
so now server side running application code is done.&lt;br&gt;
Now Let's Begin with next Step&lt;/p&gt;

&lt;h2&gt;&lt;strong&gt;Step 4&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;creat a new folder in with public name and create file with these commands as below&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir public
cd public
touch index.html
touch sw.js
touch app.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OpyA7z5h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/FMH7LgpjQoiL2n5wFPtc" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OpyA7z5h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/FMH7LgpjQoiL2n5wFPtc" alt="create-public-dir.png"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tlUZlh48--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/tBj8EHNRZ5pYPfWDQhbA" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tlUZlh48--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/tBj8EHNRZ5pYPfWDQhbA" alt="creat-public-dir-files.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;now lets beign the basic html code in &lt;strong&gt;index.html&lt;/strong&gt; file&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"X-UA-Compatible"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"ie=edge"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Web-Push Application with Restful Api&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;This is a web-push notification example&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- call service worker for register and send subscribe request to the server with javascript --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"app.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;save this code and move to next file &lt;strong&gt;app.js&lt;/strong&gt; where service worker browser check and register service worker in browser and also send a ajax request to the application API &lt;strong&gt;&lt;a href="http://host:3000/subscribe"&gt;http://host:3000/subscribe&lt;/a&gt;&lt;/strong&gt; for subscribe the service in client browser.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let isSubscribed = false;
let swRegistration = null;
let applicationKey = "put_your_public_key_here";


// Url Encription
function urlB64ToUint8Array(base64String) {
    const padding = '='.repeat((4 - base64String.length % 4) % 4);
    const base64 = (base64String + padding)
        .replace(/\-/g, '+')
        .replace(/_/g, '/');

    const rawData = window.atob(base64);
    const outputArray = new Uint8Array(rawData.length);

    for (let i = 0; i &amp;lt; rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i);
    }
    return outputArray;
}

// Installing service worker
if ('serviceWorker' in navigator &amp;amp;&amp;amp; 'PushManager' in window) {
    console.log('Service Worker and Push is supported');

    navigator.serviceWorker.register('sw.js')
        .then(function (swReg) {
            console.log('service worker registered');

            swRegistration = swReg;

            swRegistration.pushManager.getSubscription()
                .then(function (subscription) {
                    isSubscribed = !(subscription === null);

                    if (isSubscribed) {
                        console.log('User is subscribed');
                    } else {
                        swRegistration.pushManager.subscribe({
                                userVisibleOnly: true,
                                applicationServerKey: urlB64ToUint8Array(applicationKey)
                            })
                            .then(function (subscription) {
                                console.log(subscription);
                                console.log('User is subscribed');

                                saveSubscription(subscription);

                                isSubscribed = true;
                            })
                            .catch(function (err) {
                                console.log('Failed to subscribe user: ', err);
                            })
                    }
                })
        })
        .catch(function (error) {
            console.error('Service Worker Error', error);
        });
} else {
    console.warn('Push messaging is not supported');
}

// Send request to database for add new subscriber
function saveSubscription(subscription) {
    let xmlHttp = new XMLHttpRequest();
    //put here API address
    xmlHttp.open("POST", "/subscribe");
    xmlHttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
    xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readyState != 4) return;
        if (xmlHttp.status != 200 &amp;amp;&amp;amp; xmlHttp.status != 304) {
            console.log('HTTP error ' + xmlHttp.status, null);
        } else {
            console.log("User subscribed to server");
        }
    };

    xmlHttp.send(JSON.stringify(subscription));
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and now save the all files and start coding for a service worker let's begin now&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let notificationUrl = '';
//notification registered feature for getting update automatically from server api
self.addEventListener('push', function (event) {
    console.log('Push received: ', event);
    let _data = event.data ? JSON.parse(event.data.text()) : {};
    notificationUrl = _data.url;
    event.waitUntil(
        self.registration.showNotification(_data.title, {
            body: _data.message,
            icon: _data.icon,
            tag: _data.tag
        })
    );
});

//notification url redirect event click
self.addEventListener('notificationclick', function (event) {
    event.notification.close();

    event.waitUntil(
        clients.matchAll({
            type: "window"
        })
        .then(function (clientList) {
            if (clients.openWindow) {
                return clients.openWindow(notificationUrl);
            }
        })
    );
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;nad save the all code . YEAH..!! done. so now we have to check wheater is it working or not. so again run command in  your terminal &lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node server.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;open &lt;strong&gt;url: &lt;a href="http://localhot:3000"&gt;http://localhot:3000&lt;/a&gt;&lt;/strong&gt; in your browser now &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NRU0LQxs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/G7sZ1AuSyOF9DHyvcA2f" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NRU0LQxs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.filestackcontent.com/G7sZ1AuSyOF9DHyvcA2f" alt="puh-popup.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;after click on allo you see message like in your browser console&lt;/p&gt;


</description>
      <category>node</category>
      <category>mongodb</category>
      <category>pushnotification</category>
      <category>webpush</category>
    </item>
  </channel>
</rss>
