Build PWA
you're proud to ship

100% free, zero-config PWA install panels and custom push notification manager widgets. Built with React and Typescript.

Settings
P

pwa-notifications

Active Workspace

Push Notifications Toggle real-time alerts

Install on Your Device

Add to your home screen for fast access.

Subscribed successfully!

You are offline

Please check your internet connection.

Everything you need to ship.

All PWA features pre-handled: iOS Safari instructions, interactive install panels, and custom subscription widgets.

Intelligent Installation

Auto-detects browser capabilities, renders specific prompts for iOS, Android, or desktop, and manages dismiss states locally.

Push Manager Switch

A clean checkbox switch component that safely registers service workers and subscribes/unsubscribes to push notifications.

Custom Prompt Dialog

Avoid default browser prompt dialogs. Renders premium custom in-app action sheets matching modern UI/UX principles.

Offline Network Alerts

Automatically detects when users lose internet connection and provides non-intrusive toasts to keep them informed.

Step-by-step

Get started in minutes

1

Install the library

Run this terminal command in your root directory to install the package dependencies.

What happens next? The library will automatically inject the components into your root layout. You will instantly see the "Install App" section at the bottom of your page, and the standard install icon will appear in the browser's address bar!

npm i pwa-notifications
2

Configure Manifest

Edit your custom values in the newly injected public/manifest.json.

{
  "name": "My Application",
  "short_name": "App",
  "description": "Always Connected",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#0f172a",
  "icons": [
    {
      "src": "/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}
3

Send Push Notifications

In your backend, use the web-push package along with the generated VAPID keys in your .env file to send notifications to subscribed clients.

Note: The subscription object is automatically generated by the client component when a user turns notifications on. You should save this object to your database.

// 1. Install web-push on your backend: npm install web-push
const webpush = require("web-push");

// 2. Configure VAPID keys (found in your generated .env file)
webpush.setVapidDetails(
  "mailto:your-email@example.com",
  process.env.VAPID_PUBLIC_KEY, // Use NEXT_PUBLIC_ or VITE_ prefix if applicable
  process.env.VAPID_PRIVATE_KEY
);

// 3. Send a push payload to a saved user subscription
const userSubscription = { /* retrieved from your database */ };
const payload = JSON.stringify({ 
  title: "New Match!", 
  body: "Check your alerts for the latest updates." 
});

webpush.sendNotification(userSubscription, payload)
  .then(() => console.log("Alert sent successfully!"))
  .catch(err => console.error("Error sending alert:", err));

Deep Dive

Advanced Usage & Architecture

Manual usage instructions for frameworks without auto-injection, and best practices for scaling push notifications.

Usage in Standard React (Vite / CRA)

If you are not using Next.js, the package will still generate the required sw.js and keys, but you will need to manually hook up the UI using the client API.

import { useEffect, useState } from 'react';
import { registerServiceWorker, subscribeToPush, isPushSupported, onPWAInstallable, promptPWAInstall } from "pwa-notifications/client";

export default function App() {
  const [canInstall, setCanInstall] = useState(false);

  useEffect(() => {
    registerServiceWorker("/sw.js");
    return onPWAInstallable((installable) => setCanInstall(installable));
  }, []);

  const handleSubscribe = async () => {
    if (!isPushSupported()) return alert("Push not supported!");
    const subscription = await subscribeToPush({
      vapidKey: import.meta.env.VITE_VAPID_PUBLIC_KEY
    });
    // Send subscription to your backend
  };

  return (
    <div>
      <button onClick={handleSubscribe}>Enable Notifications</button>
      {canInstall && <button onClick={promptPWAInstall}>Install App</button>}
    </div>
  );
}

Usage in Vue 3

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { registerServiceWorker, subscribeToPush, isPushSupported, onPWAInstallable, promptPWAInstall } from "pwa-notifications/client";

const canInstall = ref(false);
let cleanupInstallable = null;

onMounted(() => {
  registerServiceWorker("/sw.js");
  cleanupInstallable = onPWAInstallable((installable) => {
    canInstall.value = installable;
  });
});

onUnmounted(() => {
  if (cleanupInstallable) cleanupInstallable();
});

const handleSubscribe = async () => {
  if (!isPushSupported()) return alert("Push not supported!");
  const subscription = await subscribeToPush({
    vapidKey: import.meta.env.VITE_VAPID_PUBLIC_KEY
  });
  // Send subscription to your backend
};
</script>

<template>
  <div>
    <button @click="handleSubscribe">Enable Notifications</button>
    <button v-if="canInstall" @click="promptPWAInstall">Install App</button>
  </div>
</template>

Server-Side API

Import from pwa-notifications/server to send push notifications securely from your Node.js backend.

import { sendPushNotification } from "pwa-notifications/server";

// Example payload structure
const subscription = { /* Retrieved from database */ };

await sendPushNotification(subscription, {
  title: "New Alert!",
  body: "You have a new message.",
  icon: "/icon-192x192.svg",
  url: "/"
}, {
  vapidPublicKey: process.env.VAPID_PUBLIC_KEY,
  vapidPrivateKey: process.env.VAPID_PRIVATE_KEY
});

Architecture Guide: Real-Time Hybrid Pattern

For complex applications (like marketplaces or dashboard systems), developers often need real-time UI updates combined with OS-level PWA background push notifications. A generic, highly efficient architecture is the Hybrid Database/Real-Time Sync Pattern:

  1. Database: Source of truth (Neon, Postgres, MySQL).
  2. Real-Time Trigger: Firestore, SSE, or Supabase. A counter is incremented when a notification is created.
  3. PWA Notifications: Registers service worker and subscriber endpoint.
import { useEffect, useState } from "react";
import { registerServiceWorker, subscribeToPush } from "pwa-notifications/client";
import { onSnapshot, doc } from "firebase/firestore"; // Or your preferred websocket listener

export function useNotifications(userId: string) {
  const [notifications, setNotifications] = useState([]);

  useEffect(() => {
    // 1. Register PWA Service Worker
    registerServiceWorker("/sw.js");

    // 2. Real-time trigger: refresh UI list when counter updates
    const unsubscribe = onSnapshot(doc(db, "users", userId), () => {
      // Fetch notifications from DB and update UI
    });

    return () => unsubscribe();
  }, [userId]);

  return { notifications };
}

Help Center

Frequently Asked Questions

The library automatically injects a lightweight `NetworkAlert` component. It gracefully shows an offline toast when the connection drops, and notifies users once they are back online—all without any manual setup.

No. The installation script acts as a "meta-bundler", automatically generating and injecting an optimized `sw.js` and `manifest.json` right into your project's public directory during post-install.

Both are supported! The package detects your framework upon installation and injects the exact components needed—whether they are React/Next.js components or Vue/Nuxt files.

The library automatically generates highly-secure VAPID public/private key pairs and adds them to your local environment variables. Your frontend handles the public key subscription while your backend securely fires the push events.