Aparx Logo
Web Development 6 min read • Aug 14, 2026

Mastering Web Push Notifications with VAPID and Service Workers

Implement native browser push notifications without proprietary SDKs. Understand VAPID keypairs, PushManager subscription objects, and background push handlers.

AO
Aparx Frontend Team
Aparx Software Engineering
Advertisement

Until recently, delivering real-time alerts to mobile users required publishing native mobile apps to the App Store or Google Play. Today, modern Progressive Web Apps (PWAs) running on both desktop and mobile browsers can receive native background push notifications even when the browser tab is completely closed.

Here is how to implement the Web Push standard cleanly using Voluntary Application Server Identification (VAPID).

The Web Push Architecture

+--------------------------------------------------------------+
|                     Web Push Architecture                    |
|                                                              |
|   1. [Browser] Requests user notification permission         |
|   2. [Browser] Subscribes to Browser Push Service (Mozilla)  |
|   3. [Push Service] Returns Subscription Endpoint + Keys     |
|   4. [Browser] Sends Subscription JSON to Your Backend       |
|                                                              |
|   When alert occurs:                                         |
|   5. [Your Backend] Signs payload with VAPID Private Key     |
|   6. [Your Backend] Sends encrypted payload to Push Service  |
|   7. [Push Service] Dispatches message to device             |
|   8. [Service Worker] Wakes up and triggers showNotification |
+--------------------------------------------------------------+

1. Registering the Service Worker in Frontend

// Register Service Worker
const registration = await navigator.serviceWorker.register('/sw.js');

// Subscribe to push
const subscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY)
});

// Send subscription object to Laravel / Express backend
await fetch('/api/push/subscribe', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(subscription)
});

2. Handling the Push Event in `sw.js`

// public/sw.js
self.addEventListener('push', function(event) {
  const data = event.data ? event.data.json() : {};
  
  event.waitUntil(
    self.registration.showNotification(data.title || 'Aparx Notification', {
      body: data.message,
      icon: '/images/aparx-logo.png',
      badge: '/favicon.png',
      data: { url: data.target_url || '/' }
    })
  );
});

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(clients.openWindow(event.notification.data.url));
});

Web push provides immediate, low-latency client re-engagement for invoice payment alerts, support ticket updates, and system monitoring with zero third-party platform licensing fees.

Advertisement

Need an Enterprise System Built?

From offline-first mobile apps to full-scale SaaS platforms, our team can engineer your solution.