How to Display Web Chat Notifications

5 min read
Ayooluwa I.
Ayooluwa I.
Published February 18, 2020

In any chat application, one of the most integral features is being able to notify users of new messages. While providing this feature comes with its own set of challenges (listeners, timing, notification types, keeping track of which messages are read, etc.), notifying users of unread messages doesn't have to be challenging.

Among the many ways in which building a chat app/feature becomes infinitely easier when building with Stream Chat is the fact that the capabilities for displaying notifications for various actions are built right into the service; the only thing you need to do is hook it up with the notification system of the platform you’re building for!

In this article, we’ll explore how you can display notifications when a user receives a new message. We’ll talk about how to prompt the user to enable notifications, then show how to listen for events that we can then hook into for notifications.

Here’s a live demo of what we’ll be building:

Prerequisites

To follow along with this tutorial, you'll need to have Node.js and npm installed on your computer. You'll also need to have some experience with building React applications.

Logging In to Stream

Create a free Stream account or sign in to your existing account here. Once you’re logged in, create a new application and take note of your App Access Keys which we’ll be making use of shortly.

Setting Up Your React App

Open the terminal on your computer and run the following command to bootstrap a new React application:

sh
    npx create-react-app stream-web-notifications

Once the command finishes running, cd into the newly created directory and install the following dependencies, which will be needed in the course of fleshing out our demo application:

sh
$ npm install express cors dotenv body-parser random-username-generator stream-chat stream-chat-react axios

After the dependencies are installed, you can start the development server using npm start which should open it up on http://localhost:3000!

Setting Up Your Server

Before we can build the application frontend, we need to set up an Express server for the purpose of creating users on our Stream instance and resolving special tokens, which are used to authenticate the user.

Create a new server.js in the root of your project directory and populate it with the following code:

// server.js

require('dotenv').config();

const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const { StreamChat } = require('stream-chat');

const app = express();

app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

The code above allows us to receive a username from the client, and create the user on our Stream chat instance, passing in the token for the user. The token is also included in the response, allowing us to use it to initialise the user in our React application.

Before we can start the server, we need to set some environmental variables. Create a .env file in the project and paste your Stream application credentials (which you grabbed when you logged in to your account) into the file in the following format:

// .env
STREAM_API_KEY=<your api key>
STREAM_APP_SECRET=<your app secret>

Now go ahead and start your server on port 7000 with node server.js!

Building Your Application Frontend

Building your own app? Get early access to our Livestream or Video Calling API and launch in days!

Our application code will be quite simple, thanks to our use of Stream’s React components, which enable us to compose a rich chat interface with only a few lines of code. Here’s all the code we'll need to build out the UI for our chat app:

// src/App.js

import React, { useState, useEffect } from 'react';
import './App.css';
import {
  Chat,
  Channel,
  ChannelHeader,
  Thread,
  Window,
  ChannelList,
  ChannelListTeam,
  MessageList,
  MessageTeam,
  MessageInput,

And there you go... With just the lines of code above, we have a fully responsive chat UI that supports advanced chat functionality, such as typing indicators, emoji, reactions, file uploads, rich link preview, user presence and more!

With this code, we’re generating a random username each time the page is loaded, so we don’t have to go through a complicated sign-in process to see the app in action. This also makes it easy to spawn multiple users quickly and to simulate a chat session between them.

In the next section, we’ll consider how to display notifications when messages are sent and received between users.

Enabling Browser Notifications for New Messages

Let’s prompt the user to enable browser notifications by displaying a banner at the top of the page, similarly to the way it’s done in Slack. Update the code in src/App.js as follows:

// src/App.js

import React, { useState, useEffect } from 'react';
import './App.css';
import {
  Chat,
  Channel,
  ChannelHeader,
  Thread,
  Window,
  ChannelList,
  ChannelListTeam,
  MessageList,
  MessageTeam,
  MessageInput,

You'll also need to add some styles for the banner in your src/App.css file as shown below:

/* src/App.css */

.alert {
  text-align: center;
  background-color: #006CFF;
  color: #fff;
  padding: 15px;
}

.alert p {
  margin: 0;
}

.alert button {
  background-color: transparent;

The setNotificationBanner hook helps us determine whether to show the alert banner or not. If the user hasn’t granted or denied permission, the banner is shown and, once it's clicked, a prompt is displayed by the browser asking the user to block or allow notifications from the app.

Now that notifications are enabled, the next thing to figure out is a way to display notifications when a user has a new unread message. One method we’ll employ is to change the favicon on the browser window, to give the user multiple indications that a message or few has not yet been read, which is a common technique employed by many web applications today! Once all the messages have been read, we’ll revert back to the normal favicon.

Open your public/index.html file and add an id of favicon to the favicon link element:

html
<link id="favicon" rel="icon" href="%PUBLIC_URL%/favicon.ico" />

Following that, update your src/App.js file as shown below:

// src/App.js

import React, { useState, useEffect } from 'react';
import './App.css';
import {
  Chat,
  Channel,
  ChannelHeader,
  Thread,
  Window,
  ChannelList,
  ChannelListTeam,
  MessageList,
  MessageTeam,
  MessageInput,

The relevant changes are between lines 53-66. Stream provides an easy way to listen for events on a channel; you can listen for a specific event or for all events, as we’re doing above.
If the message.new event is triggered, and the unread_count is greater than 0, we display a notification for the user and set the favicon to a bell icon. Checking the value of unread_count is necessary because we don’t want to display a notification for messages that have already been read.

Secondly, if the message.read event is triggered, and the total_unread_count is falsy (set to 0 or undefined or null), we revert to the regular favicon; if the total_unread_count is falsy, it is an indication that the user has no unread messages.

You can try out your handiwork by using two different browsers to send messages between users. It should send notifications and update the favicons appropriately. You will also notice that the title of the window is updated with the number of unread messages that a user has. This is an automatic feature that we get just by making use of Stream’s React components!

Wrapping Up!

In this tutorial, we’ve described how to set up real time browser notifications for incoming messages with Stream. The Stream Chat docs contain more information on the various types of events that can be listened for, so be sure to check it out to see everything that’s available to you!

The complete source code used in this tutorial can be found in the GitHub repository. Thanks for reading!

decorative lines
Integrating Video With Your App?
We've built an audio and video solution just for you. Launch in days with our new APIs & SDKs!
Check out the BETA!