<div id = "contentMain">
<div>
<center>
<img src = "https://res.cloudinary.com/dzemqknqv/image/upload/v1614008869/11_irslix.png" class = "img-fluid" />
</center> <br/> <br/>
</div>
<table>
<tr>
<td> Today I will teach you how to create web notifications from our Node - Express.js server to an HTML web application, the notifications will be created from the API provided by the browser, we will use a module called web push (<a target = "_ blank" href = "https://www.npmjs.com/package/web-push"> web-push </a>) that will help us create them, additionally we will use what is called Service workers ( processes that are kept running from the browser)
</td>
</tr>
</table>
<h1 style = "color: red"> NODE.js </h1>
<p> We will start by creating a folder on our desktop <code> web-notification-app-node / </code> and activating the console of our favorite code editor, and we will install the following dependencies: </p>
<div class = "gatsby-highlight">
<pre class = "gatsby-code">
<code class = "gatsby-code"> <b class = "token function"> npm </b> init --yes
</code>
</pre>
</div>
And
<div class = "gatsby-highlight">
<pre class = "gatsby-code">
<code class = "gatsby-code"> <b class = "token function"> npm </b> i express morgan dotenv web-push
</code>
</pre>
</div>
<p> We will create a file called .env where we will place our public and private keys provided by the web-push module </p>
<div> <b> .env </b> <br/> <br/> </div>
<div class = "gatsby-highlight">
<pre class = "gatsby-code">
<code class = "gatsby-code"> PUBLIC_KEY = tu_public_key_here
PRIVATE_KEY = you_private_key_here
</code>
</pre>
</div>
<br/> <br/>
<p> Once our environment variables file is created, we proceed to generate these keys, for this we will write the following in the console </p>
<div class = "gatsby-highlight">
<pre class = "gatsby-code">
<code class = "gatsby-code"> npx web-push generate-vapid-keys
</code>
</pre>
</div>
<p> This will return something like </p>
<div>
<center>
<img src = "https://res.cloudinary.com/dzemqknqv/image/upload/v1614009767/4_uyqboq.jpg" class = "img-fluid" />
</center> <br/> <br/>
</div>
<blockquote> Those keys are the ones that we will place in the .env file </blockquote>
<p> We will create a file called <code> webpush.js </code> with the following <b> configuration</b> </p>
<div> <b> src / webpush.js </b> <br/> <br/> </div>
<div class = "gatsby-highlight">
<pre class = "gatsby-code">
<code class = "gatsby-code"> const webpush = require ('web-push')
webpush.setVapidDetails (
`mailto: $ {process.env.EMAIL}`,
process.env.PUBLIC_KEY,
process.env.PRIVATE_KEY
);
module.exports = webpush
</code>
</pre>
</div>
<br/> <br/>
<p> </p>
<div> <b> src / index.js </b> <br/> <br/> </div>
<div class = "gatsby-highlight">
<pre class = "gatsby-code">
<code class = "gatsby-code"> require ('dotenv'). config ()
const express = require ('express')
const morgan = require ('morgan')
const path = require ('path')
const app = express ()
// MIDDLEWARES
app.use (morgan ('dev'))
app.use (express.urlencoded ({extended: false}))
app.use (express.json ())
// ROUTES
app.use (require ('./ routes /'))
// STATICS FILES
app.use (express.static (path.join (__ dirname, 'public')))
app.listen (process.env.PORT || 3000, () => console.log ('Server on port', process.env.PORT || 3000))
</code>
</pre>
</div>
<br/> <br/>
<div> <b> We create a folder <code>routes/</code> </b> and inside an index.js file with our 2 routes <br/> <br/> </div>
<div> <b> routes / index.js </b> <br/> <br/> </div>
<div class = "gatsby-highlight">
<pre class = "gatsby-code">
<code class = "gatsby-code"> const {Router} = require ('express')
const router = Router ()
const webpush = require ('../ webpush')
let pushSubscripton;
router.post ('/ subscribeUser', async (req, res) => {
pushSubscripton = req.body;
res.status (200) .json ();
})
router.post ('/ new-msg', async (req, res) => {
const {title, message} = req.body;
const payload = JSON.stringify ({
title,
message
});
res.status (200) .json ();
try {
await webpush.sendNotification (pushSubscripton, payload);
} catch (error) {
console.log (error);
}
})
module.exports = router
</code>
</pre>
</div>
<br/> <br/>
<div> We will create a <code> public / </code> folder and inside a file index.html, main.js and serviceWorker.js <br/> <br/> </div>
<div> <b> public / index.html </b> <br/> <br/> </div>
<div class = "gatsby-highlight">
<pre class = "gatsby-code">
<code class = "gatsby-code"> <! DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta http-equiv = "X-UA-Compatible" content = "IE = edge">
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
<title> How to send notifications to the browser (wep push) using Node.js and Service Workers </title>
<link href = "https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel = "stylesheet"
integrity = "sha384-BmbxuPwQa2lc / FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH / Ev + nYRRuWlolflfl" crossorigin = "anonymous">
</head>
<body>
<div class = "container mt-5 mb-2">
<h2> How to send notifications to the browser (wep push) using Node.js and Service Workers - <code> <a href="https://hive.blog/@jfdesousa7"> Jfdesousa7 </a> </code> </h2>
<div class = "col-md-4 mt-5 mx-auto">
<div class = "card">
<div class = "card-body">
<form id = "form">
<div class = "mb-4">
<input type = "text" id = "title" placeholder = "Enter the title of the message"
class = "form-control" autofocus>
</div>
<div class = "mb-4">
<textarea class = "form-control" id = "message" rows = "2"
placeholder = "Enter the message"> </textarea>
</div>
<div class = "mb-4>
<button type = "submit" class = "btn btn-primary"> Send notification </button>
</div>
</form>
</div>
</div>
</div>
</div>
<script src = "./ main.js"> </script>
</body>
</html>
</code>
</pre>
</div>
<br/> <br/>
<div> <b> public / main.js </b> <br/> <br/> </div>
<div class = "gatsby-highlight">
<pre class = "gatsby-code">
<code class = "gatsby-code"> const PUBLIC_KEY = "BPU1qVu0bNbIFdC15E4EooVBhjuOV8w40rk5NO3xR-UtF_3I7l5h5EQxeT2yXvEBS4ArrUfE7-YfKEPoLAYVi9k";
async function subscribeUser () {
const register = await navigator.serviceWorker.register ("/ serviceWorker.js", {
scope: "/",
});
const subscribe = await register.pushManager.subscribe ({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array (PUBLIC_KEY),
});
await fetch ("/ subscribeUser", {
method: "POST",
body: JSON.stringify (subscribe),
headers: {
"Content-Type": "application / json",
},
});
console.log ("Subscribed!");
}
function urlBase64ToUint8Array (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 <rawData.length; ++ i) {
outputArray [i] = rawData.charCodeAt (i);
}
return outputArray;
};
const form = document.querySelector ('# form')
const title = document.querySelector ('# title')
const message = document.querySelector ('# message')
form.addEventListener ('submit', async (e) => {
e.preventDefault ()
await fetch ('/ new-msg', {
method: "POST",
body: JSON.stringify ({
title: title.value,
message: message.value
}),
headers: {
"Content-Type": "application / json"
}
})
form.reset ()
})
subscribeUser ();
</code>
</pre>
</div>
<br/> <br/>
<div> <b> public / serviceWorker.js </b> <br/> <br/> </div>
<div class = "gatsby-highlight">
<pre class = "gatsby-code">
<code class = "gatsby-code"> self.addEventListener ("push", (e) => {
const data = e.data.json ();
self.registration.showNotification (data.title, {
body: data.message,
icon: "./images/jfdesousa7.png",
});
});
</code>
</pre>
</div>
<br/> <br/>
<p> Once we run our example with <code> node src / index.js </code> we must <b> allow </b> the browser to send notifications
<br/>
<div>
<center>
<img src = "https://res.cloudinary.com/dzemqknqv/image/upload/v1614008872/1_xlcqjh.jpg" class = "img-fluid" />
</center> <br/> <br/>
</div>
<div>
<center>
<img src = "https://res.cloudinary.com/dzemqknqv/image/upload/v1614008873/2_x0iprv.png" class = "img-fluid" />
</center> <br/> <br/>
</div>
<table>
<tr><td> <h3> And with those friends we reached the end of the tutorial, I hope you enjoyed it and until next time! </h3> </td>
</tr>
</table>
<br/>
<h2> Visit my official website for budges and much more </h2>
<center> <a href="https://tupaginaonline.net" target="_blank"> <b> TupaginaOnline.net </b> </a> </center>
</div>