Building Substack-like Application with Notification Service - Real-time lists updation and Broadcasts

Sanjeev Kumar
February 7, 2025

Keeping your audience engaged and up-to-date is crucial for the success of any online publication or newsletter service. One effective way to do this is by implementing a real-time notification system that allows you to broadcast updates and messages to your subscribers instantly. In this tutorial, we will walk you through the process of building a notification system from scratch for a Substack-type newsletter application. We will cover everything from setting up the necessary infrastructure to integrating real-time updates using web sockets. By the end of this guide, you will have a fully functional notification system that will help you keep your readers informed and coming back for more.

Technology Stack

  • Frontend - React.js, Bootstrap
  • Backend - Node.js
  • For Notifications -SuprSend NodeSDK

File structure:

Application Features

  1. Users have the ability to both subscribe and unsubscribe to any newsletters that are available.
  2. Notifications can be broadcasted to all users who have subscribed to a specific newsletter.
  3. A user has the option to subscribe to any number of newsletters they desire.

Basic Application UI:

A screenshot of a newsletterDescription automatically generated

 

A screenshot of a computerDescription automatically generated

Frontend Code:

You can create your own UI, or checkout the frontend code for the developed Substack type application on Github: SuprSend-NotificationAPI/Suprsend-Newsletter: Suprsend Newsletter

Backend Code and Integration

Setting up Index.js

  
      require("dotenv").config();
      const express = require("express");
      const port = 4000;
      const app = express();
      const cors = require('cors');

      app.use(cors());
      app.use(express.json());

      const { Event } = require("@suprsend/node-sdk");
      const { Suprsend, SubscriberListBroadcast } = require("@suprsend/node-sdk");
      const supr_client = new Suprsend(process.env.WKEY, process.env.WSECRET);                               
        
    

Creating Lists on SuprSend using Lists API - https://docs.suprsend.com/docs/node-lists

  
       const data1 = supr_client.subscriber_lists.create({
            list_id: "TrendyBytes",
            list_name: "TrendyBytes",
            list_description: "Stay in the know about the latest trends, tech, and more with our bite-sized newsletter."
        });

        const data2 = supr_client.subscriber_lists.create({
            list_id: "WellnessWave",
            list_name: "WellnessWave",
            list_description: "A weekly wellness boost delivered to your inbox, packed with tips for a healthier you."
        });

        const data3 = supr_client.subscriber_lists.create({
            list_id: "EcoEcho",
            list_name: "EcoEcho",
            list_description: "Get your eco-friendly fix with news and tips on sustainable living and environmental updates."
        });

        const data4 = supr_client.subscriber_lists.create({
            list_id: "CultureSnap",
            list_name: "CultureSnap",
            list_description: "Explore global cultures through quick snapshots of traditions, stories, and art from around the world."
        });

        const data5 = supr_client.subscriber_lists.create({
            list_id: "BizBrief",
            list_name: "BizBrief",
            list_description: "Your quick business update stay informed about markets, money, and more in a nutshell."
        });

        const data0 = supr_client.subscriber_lists.create({
            list_id: "notasubscriber",
            list_name: "notasubscriber",
            list_description: "user is not subscribed to any of the list"
        });                      
        
    

Building Routes

Subscribing to the newsletter and hence that list

  
       /********************** Subscribe to a list **************************************/
        app.post("/subscribe/:listname", async (req, res) => {
            const { usermail } = req.body;
            const distinct_id = usermail; 
            const user = supr_client.user.get_instance(distinct_id);
            user.add_email(usermail);
            const response = user.save();
            response.then((res) => console.log("response", res));

            const data1 = supr_client.subscriber_lists.remove("notasubscriber", [distinct_id]);
            data1.then((res) => console.log(res)).catch((err) => console.log(err));

            const event_name = "NEWSSUBSCRIBED";
            let properties = {
                "name": req.params.listname
            };
            const event = new Event(distinct_id, event_name, properties);
            const response2 = await supr_client.track_event(event);
            console.log('response', response2);

            const data = supr_client.subscriber_lists.add(req.params.listname, [distinct_id]);

            data.then((res) => console.log(res)).catch((err) => console.log(err));
            res.json("Added a user");
        });                     
        
    

Unsubscribing through the list

  
			/************************* Unsubscribe to a list **************************************/


        app.post("/unsubscribe/:listname",async(req,res)=>{
            const distinct_id = req.body.usermail;
            const data = supr_client.subscriber_lists.remove(req.params.listname, [
               distinct_id
            ]);
            data.then((res) => console.log(res)).catch((err) => console.log(err));
            res.json("unsubscribed a user");
        })                    
        
    

Broadcasting message to the entire list using SuprSend broadcast API - https://docs.suprsend.com/docs/node-broadcast

  
			/************************* send notification to a list **************************************/


        app.post("/sendnotification/:listname",async(req,res)=>{
            const broadcast_body = {
                list_id: req.params.listname,
                template:  req.params.listname.toLowerCase(),
                notification_category: "transactional",
                channels: ["email"],
                data:{

                }
            }  
            const inst = new SubscriberListBroadcast(broadcast_body);
            const data = supr_client.subscriber_lists.broadcast(inst);
            data.then((res) => console.log(res)).catch((err) => console.log(err));
            res.json("notification sent");
        })


        /************************* listening of port **************************************/


        app.listen(port,()=>{
            console.log("server started on port 4000");
        })                
        
    

Sample Email upon Subscription to any Newsletter from the UI

A screenshot of a computerDescription automatically generated

Written by:
Sanjeev Kumar
Engineering, SuprSend
Implement a powerful stack for your notifications