/how-to-build-replit

How to Build a Notification system with Replit

Learn how to build a powerful notification system with Replit. Follow easy steps to send alerts, improve user engagement, and enhance your app’s experience.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

How to Build a Notification system with Replit

A simple, reliable way to build a notification system on Replit is to create a small backend using Node.js with Express and connect it to your frontend via Socket.IO. Socket.IO allows realtime communication between the server and clients, which makes it perfect for sending live notifications. You’ll store events in-memory or in a small database (like SQLite or Replit’s built-in database), and whenever a new event happens, you’ll broadcast it to all connected users. This approach runs smoothly in Replit and works even when you refresh or have multiple collaborators connected.

 

Project Structure

 

You’ll have these files in your Replit project:

  • index.js — Your Node.js server (Express + Socket.IO setup).
  • public/index.html — The frontend where users see notifications.
  • (Optional) public/script.js — JavaScript for handling incoming notifications in the browser.

 

1. Setup the Backend (index.js)

 

In your main index.js file, paste the following code. This file runs automatically when you click “Run” on Replit because package.json points to this file as the main entry.

// Import dependencies
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');

// Setup app and server
const app = express();
const server = http.createServer(app);
const io = new Server(server);

// Serve static files
app.use(express.static('public'));

// Simple route check
app.get('/ping', (req, res) => {
  res.send('Server is alive!');
});

// Listen for new connections from clients
io.on('connection', (socket) => {
  console.log('A user connected:', socket.id);

  // Example: respond when client requests a fake notification
  socket.on('sendNotification', (data) => {
    console.log('Notification received on server:', data);
    // Broadcast to all connected clients
    io.emit('newNotification', data);
  });

  socket.on('disconnect', () => {
    console.log('User disconnected:', socket.id);
  });
});

// Start the server using Replit PORT
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => console.log(`Server running on port ${PORT}`));

 

Explanation:

  • express.static('public') tells the server to serve your frontend files from the public folder.
  • io.emit() sends a message to all clients connected to Socket.IO — that’s how notifications are broadcast instantly.
  • All console logs appear in your Replit Log window.

 

2. Create Frontend Files

 

Create a new folder named public in your project’s root. Inside it, add two files: index.html and script.js.

 

public/index.html

 

<!DOCTYPE html>
<html>
  <head>
    <title>Replit Notifications</title>
  </head>
  <body>
    <h2>Realtime Notifications</h2>
    <button id="notifyBtn">Send Test Notification</button>
    <ul id="notificationList"></ul>

    <!-- Socket.io client library -->
    <script src="/socket.io/socket.io.js"></script>
    <script src="script.js"></script>
  </body>
</html>

 

public/script.js

 

// Connect to Socket.IO server
const socket = io();

// Elements from the DOM
const notifyBtn = document.getElementById('notifyBtn');
const notificationList = document.getElementById('notificationList');

// When the button is clicked, send a new notification event to server
notifyBtn.addEventListener('click', () => {
  const newNotif = { text: 'Hello! This is a real-time notification.' };
  socket.emit('sendNotification', newNotif);
});

// When the server sends a new notification, display it
socket.on('newNotification', (data) => {
  const li = document.createElement('li');
  li.textContent = data.text;
  notificationList.appendChild(li);
});

 

3. Running it on Replit

 

  • Click the green Run button. You’ll see logs saying “Server running on port …” in the console.
  • Click the “Open in new tab” icon once the web preview loads.
  • Click your “Send Test Notification” button — you should see new list items appear instantly.
  • If you open the project URL in another tab, both pages will receive the same notification instantly.

 

4. Optional Enhancements

 

  • Persist notifications: Add a simple database (SQLite or Replit DB) and save the data each time a new notification is created, so it survives page refreshes.
  • Use Secrets: If connecting to an external API (for example, to send email notifications), store your API keys under the “Secrets” tab in Replit (lock icon on left side).
  • Styling: Add a public/style.css to make the notifications look nice. Link it in your HTML head with <link rel="stylesheet" href="style.css">.

 

This setup is fully compatible with Replit’s built-in hosting, collaboration, and automatic restarts. It’s lightweight, uses only standard Express + Socket.IO, and can be extended later for production APIs or databases easily.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Contact Us

How to Build a Simple Notification API with Express on Replit


const express = require("express");
const { v4: uuid } = require("uuid");
const app = express();

app.use(express.json());

let userNotifications = {}; // key: userId, value: array of notifications

function createNotification(userId, message, type = "info") {
  const note = {
    id: uuid(),
    message,
    type,
    read: false,
    createdAt: new Date().toISOString(),
  };
  if (!userNotifications[userId]) userNotifications[userId] = [];
  userNotifications[userId].unshift(note);
  return note;
}

app.post("/notify", (req, res) => {
  const { userId, message, type } = req.body;
  if (!userId || !message) return res.status(400).json({ error: "Missing fields" });
  const note = createNotification(userId, message, type);
  res.json(note);
});

app.get("/notifications/:userId", (req, res) => {
  const userId = req.params.userId;
  res.json(userNotifications[userId] || []);
});

app.patch("/notifications/:userId/:id/read", (req, res) => {
  const { userId, id } = req.params;
  const userNotes = userNotifications[userId];
  if (!userNotes) return res.status(404).json({ error: "User not found" });
  const note = userNotes.find(n => n.id === id);
  if (!note) return res.status(404).json({ error: "Notification not found" });
  note.read = true;
  res.json(note);
});

app.listen(3000, () => console.log("Notification API running on port 3000"));

How to Send External Notifications with Express and Discord Webhooks on Replit


const express = require("express");
const axios = require("axios");
const dotenv = require("dotenv");

dotenv.config();
const app = express();
app.use(express.json());

// Example: send notification using an external service (Discord Webhook)
async function sendExternalNotification(userId, message) {
  const webhookUrl = process.env.DISCORD_WEBHOOK_URL;
  if (!webhookUrl) {
    throw new Error("Missing Discord webhook URL");
  }

  const payload = {
    content: `🔔 Notification for <@${userId}>: ${message}`,
  };

  return await axios.post(webhookUrl, payload);
}

app.post("/notify-external", async (req, res) => {
  const { userId, message } = req.body;
  if (!userId || !message) return res.status(400).json({ error: "Missing parameters" });

  try {
    await sendExternalNotification(userId, message);
    res.json({ success: true, deliveredTo: "Discord" });
  } catch (err) {
    console.error("Error delivering notification:", err.message);
    res.status(500).json({ error: "Failed to deliver notification" });
  }
});

app.listen(3000, () => console.log("External notification endpoint running on port 3000"));

How to Build a Real-Time Notification System with Express and Socket.io


const express = require("express");
const http = require("http");
const { Server } = require("socket.io");

const app = express();
const server = http.createServer(app);
const io = new Server(server, {
  cors: { origin: "\*" }
});

app.use(express.json());

let activeUsers = new Map(); // userId -> socketId
let pendingNotifications = {}; // userId -> [notification objects]

io.on("connection", (socket) => {
  socket.on("register", (userId) => {
    activeUsers.set(userId, socket.id);
    if (pendingNotifications[userId]) {
      pendingNotifications[userId].forEach(note => {
        socket.emit("notification", note);
      });
      delete pendingNotifications[userId];
    }
  });

  socket.on("disconnect", () => {
    for (let [userId, id] of activeUsers.entries()) {
      if (id === socket.id) {
        activeUsers.delete(userId);
        break;
      }
    }
  });
});

app.post("/send-notification", (req, res) => {
  const { userId, message, type } = req.body;
  if (!userId || !message) return res.status(400).json({ error: "Missing fields" });

  const notification = {
    id: Date.now().toString(),
    message,
    type: type || "info",
    sentAt: new Date().toISOString()
  };

  const socketId = activeUsers.get(userId);
  if (socketId) {
    io.to(socketId).emit("notification", notification);
  } else {
    if (!pendingNotifications[userId]) pendingNotifications[userId] = [];
    pendingNotifications[userId].push(notification);
  }

  res.json({ delivered: !!socketId });
});

server.listen(3000, () => console.log("Real-time notification system is running"));

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Contact Us
Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Best Practices for Building a Notification system with Replit

A solid notification system on Replit usually means sending real-time or queued messages (like in-app alerts, emails, or browser push notifications) from your backend (Node.js or Python) to users. The key is to keep the architecture simple, reliable, and aligned with Replit’s limits — Replit Repls can sleep when inactive, so you should use an external service (like Upstash Redis, Firebase, or a hosted database) to persist notification data, and a lightweight frontend system (like React or plain JS) to display them. The simplest working pattern: store notifications in your database, use WebSocket or polling to deliver new ones, and update the client UI when new notifications arrive.

 

Step 1: Create a backend endpoint for storing notifications

 

Inside Replit, your main backend file (often called index.js or server.js) is where you initialize the Express server. We’ll add a new route for saving notifications. If you don’t have Express installed yet, run this in the shell:

npm install express

Then, in your index.js file:

// index.js
const express = require("express")
const bodyParser = require("body-parser")
const app = express()
const PORT = process.env.PORT || 3000

app.use(bodyParser.json())

// temporary "in-memory" notifications store
// for production, you should use a real DB (like Replit DB, MongoDB Atlas, or Upstash Redis)
let notifications = []

// endpoint to add new notification
app.post("/api/notify", (req, res) => {
  const { message } = req.body
  if (!message) return res.status(400).json({ error: "Message is required" })
  const note = { id: Date.now(), message }
  notifications.push(note)
  res.json({ success: true, note })
})

// endpoint to get notifications
app.get("/api/notifications", (req, res) => {
  res.json(notifications)
})

app.listen(PORT, () => console.log(`Server running on port ${PORT}`))

This creates two HTTP endpoints: one to save a notification, and one to fetch all notifications. For real-world usage, replace the in-memory array with a Replit DB or Redis instance so data persists across restarts.

 

Step 2: Connect to a database so data survives restarts

 

Using Replit’s built-in DB is simplest for small projects. Create a file named db.js in the root of your Repl, with this:

// db.js
const Database = require("@replit/database")
const db = new Database()
module.exports = db

Then update your index.js to store notifications persistently:

// replace the in-memory array logic
const db = require("./db")

app.post("/api/notify", async (req, res) => {
  const { message } = req.body
  const note = { id: Date.now(), message }
  await db.set(`note_${note.id}`, note)
  res.json({ success: true, note })
})

app.get("/api/notifications", async (req, res) => {
  const keys = await db.list("note_")
  const allNotes = []
  for (let key of keys) {
    const item = await db.get(key)
    allNotes.push(item)
  }
  res.json(allNotes)
})

Replit DB persists automatically, so your notifications won’t disappear when the Repl restarts.

 

Step 3: Enable live updates using WebSocket (Socket.io)

 

This lets you push notifications to the browser without refreshing. Install Socket.io:

npm install socket.io

Then modify your index.js (add this after app.listen()):

const http = require("http").Server(app)
const io = require("socket.io")(http, {
  cors: { origin: "*" } // simple CORS for dev
})

// Listen for client connections
io.on("connection", (socket) => {
  console.log("User connected", socket.id)

  socket.on("disconnect", () => {
    console.log("User disconnected", socket.id)
  })
})

// Broadcast new notification after it’s created
app.post("/api/notify", async (req, res) => {
  const { message } = req.body
  const note = { id: Date.now(), message }
  await db.set(`note_${note.id}`, note)
  io.emit("new_notification", note) // send to all connected clients
  res.json({ success: true, note })
})

http.listen(PORT, () => console.log(`Server with Socket.io running on port ${PORT}`))

Now your backend broadcasts notifications in real time to all open browsers.

 

Step 4: Frontend to listen and display notifications

 

If you have a public folder for your frontend (like public/index.html), insert this in the HTML body:

<div id="notifications"></div>

<script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
<script>
  const socket = io() // connects automatically to the same origin
  const container = document.getElementById("notifications")

  socket.on("new_notification", (note) => {
    const div = document.createElement("div")
    div.textContent = "🔔 " + note.message
    container.prepend(div)
  })
</script>

This will instantly show each new notification without reloading the page.

 

Step 5: Use Secrets for sensitive keys (if integrating email/push)

 

If your notifications include third-party services (like email via SendGrid, or push via Firebase), never hardcode keys. In Replit, set them in the Secrets tab (lock icon on left sidebar). For example:

// config.js
module.exports = {
  SENDGRID_API_KEY: process.env.SENDGRID_API_KEY
}

Then access them from your backend normally. Secrets stay out of your public code and are safe from exposure.

 

Step 6: Deployment & Pitfalls

 

  • Keep your backend awake: Use UptimeRobot or Replit’s deployment plan if you need continuous service. Free Repls sleep after inactivity.
  • Don’t abuse in-memory arrays: Every restart wipes them. Always use persistent storage for notifications.
  • Watch logs: Replit’s console shows live logs — use console.log() liberally to debug.
  • Multiplayer editing caution: If editing with others at the same time, make sure your team communicates when restarting the Repl, since live processes can be interrupted.

 

Wrap-up

 

On Replit, the most reliable notification system uses a simple Express server, Replit DB for persistence, and Socket.io for real-time delivery. This approach stays lightweight, works with Replit’s limitations, and runs stably even as you scale to moderate traffic. You can later extend it with email, mobile, or push APIs—all while following the same principles: persist data, emit updates, and never rely solely on in-memory storage.

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022