Skip to content

Repository files navigation

Jop PWA Logo


Jop PWA

Headless, type-safe PWA primitives for the web. Manage push notification subscriptions, service worker lifecycle, and permissions through a consistent, framework-agnostic API.

  • Headless — no UI, no opinions, just the primitives
  • Type-safe — built in TypeScript with strict types throughout
  • Reactive state — powered by @tanstack/store for fine-grained updates
  • SSR-safe — defers all browser work to mount(), works in Next.js and other SSR setups
  • Framework-agnostic — use directly or pair with an adapter

Packages

Quick start

import { PWAManager } from "@jopgood/pwa-core";

const manager = new PWAManager({
  serviceWorkerUrl: "/sw.js",
  vapidPublicKey: "YOUR_VAPID_PUBLIC_KEY",
  onSubscriptionChange: (subscription) => {
    // send subscription to your backend
  },
});

manager.mount();
manager.requestNotificationPermission();
manager.subscribe();

With React

import { PWAManager } from "@jopgood/pwa-core";
import { PushProvider, usePushNotifications } from "@jopgood/react-pwa";

const manager = new PWAManager({
  serviceWorkerUrl: "/sw.js",
  vapidPublicKey: "YOUR_VAPID_PUBLIC_KEY",
});

function App() {
  return (
    <PushProvider manager={manager}>
      <PushDemo />
    </PushProvider>
  );
}

function PushDemo() {
  const { permission, isSubscribed, subscribe, requestPermission } =
    usePushNotifications();

  return (
    <div>
      <p>Permission: {permission}</p>
      <button onClick={requestPermission}>Request permission</button>
      <button
        onClick={subscribe}
        disabled={permission !== "granted" || isSubscribed}
      >
        Subscribe
      </button>
    </div>
  );
}

Examples

Get involved

About

Headless, type-safe PWA primitives for the web — push subscriptions, service worker lifecycle, and permissions.

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages