← Back to list

Implementing Push Notifications in Next.js using Web Push and Server Actions

This guide walks you through end‑to‑end implementation of Web Push Notifications in Next.js (App Router) using Service Workers, Web Push…

Amir · 2026-01-22 01:18 · 9 claps · 2.3 min read
#nextjs #push-notification #nodejs #web-development
Open on Medium ↗
Wiki topics: 🌐 · Web Development

Implementing Push Notifications in Next.js using Web Push and Server Actions

This guide walks you through end‑to‑end implementation of Web Push Notifications in Next.js (App Router) using Service Workers, Web Push Protocol, VAPID keys, and Server Actions.

By the end, you’ll have:

  • A working push notification system
  • Browser permission handling
  • Push subscription storage
  • Server‑side notification sending

Table of Contents

  1. What Are Web Push Notifications?
  2. Architecture Overview
  3. Prerequisites
  4. Project Setup
  5. Generating VAPID Keys
  6. Service Worker Setup
  7. Requesting Notification Permission
  8. Subscribing the User
  9. Storing Subscriptions
  10. Sending Push Notifications (Server Actions)
  11. Testing & Debugging
  12. Common Pitfalls
  13. Production Considerations
  14. Conclusion

1. What Are Web Push Notifications?

Web Push Notifications allow websites to send messages to users even when the site is closed.

Key components:

  • Service Worker — Runs in the background
  • Push API — Subscribes users
  • Notification API — Displays notifications
  • Application Server — Sends messages

2. Architecture Overview

Browser
 ├── Service Worker
 ├── Push Subscription
 └── Notification UI
        ↑
        │ Web Push Protocol
        ↓
Next.js Server Actions
 ├── VAPID Auth
 ├── Subscription Store
 └── Push Sender

3. Prerequisites

  • Node.js 18+
  • Next.js 13+ (App Router)
  • HTTPS (required for push)
  • Basic React knowledge

4. Project Setup

npx create-next-app@latest web-push-demo
cd web-push-demo
npm install web-push

5. Generating VAPID Keys

VAPID keys authenticate your server with push services.

npx web-push generate-vapid-keys

You’ll get:

Public Key:  BOP...
Private Key: 9Yx...

Add them to .env.local:

NEXT_PUBLIC_VAPID_PUBLIC_KEY=your_public_key
VAPID_PRIVATE_KEY=your_private_key

6. Service Worker Setup

Create a file in public/sw.js:

self.addEventListener('push', event => {
  const data = event.data?.json();
  event.waitUntil(
    self.registration.showNotification(data.title, {
      body: data.body,
      icon: '/icon.png'
    })
  );
});

Service workers must live in /public.

NOTE : You have to make your website PWA , for that you can use this guide

7. Registering the Service Worker

'use client';

useEffect(() => {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js');
  }
}, []);

8. Requesting Notification Permission

export async function requestPermission() {
  const permission = await Notification.requestPermission();
  return permission === 'granted';
}

Best practice: request permission after user interaction.

9. Subscribing the User to Push

async function subscribeUser() {
  const registration = await navigator.serviceWorker.ready;

  const subscription = await registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: urlBase64ToUint8Array(
      process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY!
    ),
  });

  await saveSubscription(subscription);
}

Helper function:

function urlBase64ToUint8Array(base64String: string) {
  const padding = '='.repeat((4 - base64String.length % 4) % 4);
  const base64 = (base64String + padding)
    .replace(/-/g, '+')
    .replace(/_/g, '/');
  const rawData = atob(base64);

  return Uint8Array.from([...rawData].map(c => c.charCodeAt(0)));
}

10. Saving Subscriptions (Server Action)

'use server';

let subscriptions: PushSubscription[] = [];

export async function saveSubscription(sub: PushSubscription) {
  subscriptions.push(sub);
}

⚠️ In production, use a database.

11. Sending Push Notifications

'use server';

import webpush from 'web-push';

webpush.setVapidDetails(
  'admin@example.com',
  process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY!,
  process.env.VAPID_PRIVATE_KEY!
);

export async function sendNotification(message: string) {
  const payload = JSON.stringify({
    title: 'New Notification',
    body: message,
  });

  await Promise.all(
    subscriptions.map(sub =>
      webpush.sendNotification(sub, payload)
    )
  );
}

12. Triggering from UI

<button onClick={() => sendNotification('Hello from Next.js!')}>
  Send Notification
</button>

13. Testing & Debugging

  • Chrome DevTools → Application → Service Workers
  • Clear subscriptions on errors
  • Check HTTPS

14. Common Pitfalls

  • ❌ Using HTTP instead of HTTPS
  • ❌ Requesting permission on page load
  • ❌ Forgetting userVisibleOnly: true
  • ❌ Invalid VAPID keys

15. Production Considerations

  • Store subscriptions per user
  • Handle expired subscriptions (410 Gone)
  • Add click actions
  • Rate‑limit notifications

16. Conclusion

Web Push with Next.js Server Actions gives you:

  • No separate backend
  • Secure push delivery
  • Native browser notifications

This stack is perfect for SaaS dashboards, alerts, and engagement features.


메타데이터
post_id
f4b95d68091f
slug
implementing-push-notifications-in-next-js-using-web-push-and-server-actions-f4b95d68091f
url
https://medium.com/@amirjld/implementing-push-notifications-in-next-js-using-web-push-and-server-actions-f4b95d68091f
canonical_url
https://medium.com/@amirjld/implementing-push-notifications-in-next-js-using-web-push-and-server-actions-f4b95d68091f
author_url
https://medium.com/@amirjld
status
ok
fetched_at
2026-06-12 18:14:10