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…
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
- What Are Web Push Notifications?
- Architecture Overview
- Prerequisites
- Project Setup
- Generating VAPID Keys
- Service Worker Setup
- Requesting Notification Permission
- Subscribing the User
- Storing Subscriptions
- Sending Push Notifications (Server Actions)
- Testing & Debugging
- Common Pitfalls
- Production Considerations
- 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