In this tutorial, I will show how to send push notifications to your browser from your backend. We’ll use Adonis.js as our Node.js framework, and we’ll push notifications from our Adonis app to our browser through Pusher Channels.
Web push notifications are an instant means of direct communication between a website and its customers. They appear as clickable messages on web browsers in desktop and Android devices. This is the easiest way to gather more subscribers without collecting email IDs and contact details.
Here is the final result of our app:
To follow this tutorial, knowledge of JavaScript and Node.js, more precisely Adonis.js is required. You should also have the following installed on your machine:
Open your terminal and type this command to install Adonis CLI:
1# if you don't have Adonis CLI installed on your machine. 2 $ npm install -g @adonisjs/cli 3 4 # Create a new adonis app and move into the app directory 5 $ adonis new adonis-push-notifications && cd adonis-push-notifications
Start the server and test if it's working:
1$ adonis serve --dev 2 2018-10-18T09:09:16.649Z - info: serving app on http://127.0.0.1:3333
Go to the resources/views
directory and replace the content of welcome.edge
file with:
1<!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"/> 5 <title>Hello Adonis</title> 6 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> 7 <link rel="stylesheet" 8 href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/css/bootstrap.min.css"> 9 {{ style('style') }} 10 </head> 11 <body> 12 13 <div id="app" class="container" style="margin-top: 160px"> 14 <div class="row"> 15 <div class="col-md-2"></div> 16 <div class="col-md-8"> 17 <div class="card"> 18 <div class="card-header">Broadcast a Notification message</div> 19 <div class="card-body"> 20 <div class="container"> 21 <div class="row justify-content-md-center"> 22 <div class="col col-md-10"> 23 @if(old('status')) 24 <div class="alert alert-success" role="alert"> 25 <button type="button" class="close" data-dismiss="alert" aria-label="Close"> 26 <span aria-hidden="true">×</span> 27 </button> 28 {{ old('status') }} 29 </div> 30 @endif 31 <form method="POST" action="{{ route('sendNotification') }}"> 32 {{ csrfField() }} 33 <div class="form-group row"> 34 <label class="col-md-3 col-form-label"> 35 36 Notification Message 37 </label> 38 <div class="col-md-9"> 39 <input type="text" name="message" placeholder="Send Notification" 40 autocomplete="off" 41 class="form-control" required> 42 </div> 43 </div> 44 <div class="form-group row"> 45 <div class="col-md-3"></div> 46 <div class="col-md-6"> 47 <button type="submit" class="btn btn-primary btn-block"> 48 <i class="fa fa-btn fa-paper-plane"></i> Send Notification 49 </button> 50 </div> 51 </div> 52 </form> 53 </div> 54 </div> 55 </div> 56 </div> 57 </div> 58 </div> 59 </div> 60 </div> 61 62 {{ script('https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js') }} 63 {{ script('https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/js/bootstrap.min.js') }} 64 65 </body> 66 </html>
As you can see, we are importing the CSS files using the css
method. We do a similar thing with JavaScript, we use script
method to import .js
. Flash messages are used to display incoming messages from the server. Flash messages are stored temporarily in sessions by the server to display as browser notifications.
Refresh your browser:
Create a free sandbox Pusher account or sign in.
Next, create a new Pusher app instance. This registration provides credentials which can be used to communicate with the created Pusher instance. Copy the App ID, Key, Secret, and Cluster from the App Keys section and put them in the .env
file located at you project root:
1//.env 2 PUSHER_APP_KEY=<APP_KEY> 3 PUSHER_APP_SECRET=<APP_SECRET> 4 PUSHER_APP_ID=<APP_ID> 5 PUSHER_APP_CLUSTER=<APP_CLUSTER>
We’ll use these keys further in this tutorial to link Pusher with our Adonis project.
Next, we need to install the Pusher SDK as well as other dependencies we need to build our app. We won’t use the Pusher SDK directly but instead use a Pusher provider for Adonis. This provider enables us to use the Pusher SDK easily with the Adonis.js ecosystem. We should first install the Pusher SDK by running this command:
1#if you want to use npm 2 npm install pusher 3 4 #or if you prefer Yarn 5 yarn add pusher
Now, you can install the Pusher provider for Adonis with this command:
1#if you want to use npm 2 npm install adonis-pusher 3 4 #or if you prefer Yarn 5 yarn add adonis-pusher
You will need to add the provider to AdonisJS at start/app.js
:
1const providers = [ 2 ... 3 'adonis-pusher/providers/Pusher' 4 ]
In order to make requests to our backend, we need to define our routes and a controller responsible for the logic our app should have.
Type this command in your terminal to create your controller: adonis:make Notification
.
Open the routes.js
file located at ../start/routes.js
and replace the existing code with the following:
1const Route = use('Route') 2 const Event = use('Event') 3 4 Route.on('/').render('welcome') 5 6 Route.post('/sendNotification','NotificationController.sendNotification').as('sendNotification')
The first two lines pull in the Route
and Event
providers for us. Next we tell our app to render the welcome.edge
view to the /
get request. And the last route accepts a message from the client and defines the sendNotification
function (which we’ll create very soon) for handling the logic.
Now, let’s create our sendNotification
function we talked about earlier. Paste this piece of code inside your NotificationController
file:
1//../app/Controllers/Http/NotificationController.js 2 'use strict' 3 4 const Event = use('Event'); 5 6 class NotificationController { 7 8 async sendNotification({request, session, response}) { 9 10 let message = request.input('message'); 11 12 Event.emit('send::notification', message) 13 14 session.flash({status: 'Notification sent'}) 15 return response.redirect('back') 16 17 } 18 } 19 20 module.exports = NotificationController
We first pull in the Event
service provider, then we accept a message from the client post request.
Last we emit an event named send::notification
and redirect the user back with a flash message.
Create a filename event.js
in the start
directory. In this file we’ll create an event which will be fired every time we need to send a message via Pusher Channels, and as it happens a notification via Pusher Channels.
1//../start/events.js 2 const Event = use('Event') 3 const Env = use('Env') 4 const Pusher = use('Pusher') 5 6 let pusher = new Pusher({ 7 appId: Env.get('PUSHER_APP_ID'), 8 key: Env.get('PUSHER_APP_KEY'), 9 secret: Env.get('PUSHER_APP_SECRET'), 10 cluster: Env.get('PUSHER_APP_CLUSTER'), 11 encrypted: false 12 }) 13 14 //fire new event 15 Event.when('send::notification', async (message) => { 16 pusher.trigger('notification-channel', 'new-notification', { 17 message 18 }) 19 })
We need to pull in the Event
, Pusher
(using the adonis-pusher package we installed earlier) and Env
service providers.
Next, we registered a listener for the send::notification
event, after which we initialized and configure Pusher. This event was registered in the sendNotification
function we created above to handle notification post.
When we are done with the pusher configuration, we trigger a new-notification
event on the notification-channel
with the trigger
method.
The client needs to start listening to these events being emitted by Pusher. Go to the resources/views
directory and update your welcome.edge
by adding the following code:
1<!-- Include the Pusher Client library --> 2 {{ script('https://js.pusher.com/4.3/pusher.min.js') }} 3 <script> 4 5 //Open a connection to Pusher 6 let notify = ({message}) => { 7 8 if (!("Notification" in window)) { 9 alert("This browser does not support desktop notification"); 10 } 11 12 Notification.requestPermission().then(function (result) { 13 if (result === 'granted') { 14 let notification = new Notification(message) 15 } 16 }); 17 }; 18 19 20 let pusher = new Pusher(YOUR_PUSHER_APP_ID, { 21 cluster: YOUR_PUSHER_CLUSTER, 22 encrypted: false 23 }); 24 25 //Subscribe to the channel we specified in our Adonis Application 26 let channel = pusher.subscribe('notification-channel'); 27 28 //Listen for events on the channel 29 channel.bind('new-notification', (data) => { 30 notify(data) 31 }) 32 33 34 </script>
First, we include the Pusher client library in order to use Pusher instance from our browser.
As you can see we also create a notify
function. This function takes the message we intend to send as a push notification in parameter, checks if browser push notifications are supported by the browser and display a new notification to us.
Next, we initialize the Pusher service by passing in our App Key (replace with your actual keys), and some other options (cluster, encrypted). The initialized instance is used to subscribe to the notification-channel
channel.
Finally, we listened to the new-notification
event and send notifications with the notify
function we created earlier.
In summary, we learned how we can use Pusher Channels to send notifications from an Adonis.js backend. Events sent by Pusher Channels are listened on the client side and displayed as a push notifications using browser notifications web API. You can find the full source code on GitHub here.