npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

web-push-notification

v1.1.0

Published

Simple web push notifications - client and server library

Downloads

20

Readme

Web Push notification

What is it?

Web Push notification only work with two sides: A client (=Web App like React/Svelte/Astro/Vue...) and a server (=node server/cloudflare worker/deno/...). This library aims to drastically simplify both sides.

The client library part...

  • works with every framework as long as you are using vite for your build
  • thus works with Svelte, React, Vue, Qwik, Astro or just with plain JS.
  • has a tiny footprint (<1kb)
  • caveat: does install a service worker that may interferes with your primary service worker (if you have one). Further infos in the FAQ.

The server library part...

  • works currently only on Node. (More information about the FAQ.)
  • is mostly a simplified and half-modernized version of web-push.
  • Requires Node 18 or later (uses Node Fetch API)

Both libraries ...

  • have independent imports. So you don't bloat your client side footprint.
  • don't have to be used together! For example you could use Rust web_push for your server.

How to use it

Step 1: Create Vapid Keys

Just go to this link and generate them.

Step 2: Create subscription on the client side

First: npm install web-push-notification

In your client code:

import { newSubscription } from "web-push-notification/client"

// only works in safari if the user initiates this code. So a button "Subscribe now" is advised

const stringifiedNewSubscription = await newSubscription("your-applicationServerKey"); //created in step 1; return a stringified subscription (no need to stringify it again)

... and send this subscription to your node/deno/cloudflare endpoint, that we´ll create in step 3.

await fetch('https://your-domain.com/subscribe', {body: stringifiedNewSubscription})

Step 3: Create endpoint for saving on the server/function/edge function

This highly depends on your kind of server/function/edge function.

Note: currently only works in Node!

// get subscription from the request
const newSubscription = request.body //depends on your type of server and/or library (like express)

// save somewhere. Most likely a DB like Postgres.
someImaginativeDB.saveSomewhere(newSubscription)

Step 4: Send Notification

Again on the server: npm install web-push-notification

import { sendNotification } from "web-push-notification/server";

// get subscription from somewhere. Most likely a DB like Postgres.
const subscription = someImaginativeDB.get(...)

// create notification information. Full list of properties: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/showNotification
const notification = {
    title: "....",
    options: {
        body: "...",
        data: { url: "https://www.your-domain/new-blog-post" }, // Recommended workaround. Actions are buggy in Safari AND in Chromium. More about that in the FAQs.
    }
}

// your Vapid Details from Step 1
const vapidDetails = {
    'mailto:[email protected]', //This must be either a URL or a 'mailto:' address. For example: 'https://your-website.com/contact' or 'mailto: [email protected]'
    vapidPublicKey,
    vapidPrivateKey //should be stored safely. Most likely as a secret environment variable.
}

const result = await sendNotification(notification, subscription, vapidDetails);

FAQ

What about Deno and Cloudflare workers?

The original aim for this package was to develop an universal package. But unfortunately that turned out quite difficult due to two reasons: Cryptography and very specific (time-consuming) protocols.

The pain points:

  • the Encrypted Content-Encoding for HTTP (RFC 8188)
  • Voluntary Application Server Identification (VAPID) for Web Push (RFC 8292)

The OG package web-push uses outdated libraries (asn1.js -> new version would be asn1js and http_ece) and uses the "old" Crypto Node API instead of the new (universally supported) WebCrypto API. Don't get me wrong: The OG way does work perfectly but it is hard to replicate the protocols without deep knowledge about cryptography and without much spare time.

The smart solution I tried (but ultimately failed): As the tasks are only data manipulation I thought I could do an extra clever solution: One universal WASM script (these are supported in Deno, Node and Cloudflare Workers!). Rust (which can be compiled to WASM) has all the required libraries ece and vapid or even Rust web-push. Unfortunately these libraries depend on ancient c libraries that for some reasons could't be compiled to WASM.

Why is there aa special non-standard way to handle Actions ( {data: {url: ""}} )?

Main reason being the current Safari/WebKit implementation. While the official video "Meet Web Push for Safari" does display the wanted behavior, the reality is actually different. No click what so ever does emit a event.action. And in Chromium a click upon an action does open a text input prompt for whatever reason. My advice: Present options on the page you define in options.data.url (and don't use the official options.actions atm).

There is a bug or a feature is missing!

Feel free to contact me via twitter.

The repo is also open for Pull requests.

Service Worker Scope

Every service worker is installed with a scope and there can only be one for each scope. The service worker JavaScript file is placed in your assets folder by vite. Thus the scope is - you guessed it - your asset path. If you have a SW it most likely is at a root level and is not bothered. But caching the asset folder with request handling by your main SW may not work.