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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@notifizz/subscribe-react

v2.0.1

Published

React components and hooks for the Notifizz subscribe widget — multi-instance per page

Readme

@notifizz/subscribe-react

Native React components and hooks for the Notifizz subscribe widget. Multi-instance per page — mount one per Kanban card, one per thread, one per resource. State is shared automatically when two components point to the same resource.

Install

npm install @notifizz/subscribe-react

Peer dependency: React 18 or 19.

Quick start

Wrap your app once with <NotifizzProvider>:

import { NotifizzProvider } from '@notifizz/subscribe-react';

<NotifizzProvider
  apiKey={import.meta.env.VITE_NOTIFIZZ_API_KEY}
  mode="secure"
  subscriberId={user.email}
>
  <App />
</NotifizzProvider>

Drop <NotifizzSubscribe> anywhere you want a button + avatars:

import { NotifizzSubscribe } from '@notifizz/subscribe-react';

<NotifizzSubscribe resourceId="proj_42" hash={hashForProj42} />

Multi-instance — N widgets per page

function Kanban({ projects }: { projects: Project[] }) {
  return (
    <div className="grid">
      {projects.map((p) => (
        <Card key={p.id}>
          <h3>{p.name}</h3>
          <NotifizzSubscribe resourceId={p.id} hash={p.subscribeHash} />
        </Card>
      ))}
    </div>
  );
}

Two components on the same resourceId (e.g. a card + a detail panel) automatically sync — clicking subscribe in one updates the other without a refetch.

Generating the hash (secure mode)

Server-side, via a Notifizz backend SDK:

// Node.js
const hash = notifizz.generateSubscribeToken(subscriberId, resourceId);

Pass it as a prop from your server-side rendered page or fetched from your backend.

In public mode, no hash is needed.

Custom UI with useSubscription

If you need a different layout, the <NotifizzSubscribe> default doesn't fit, or you want full control:

import { useSubscription } from '@notifizz/subscribe-react';

function MyCustomButton({ resourceId, hash }: { resourceId: string; hash: string }) {
  const {
    isSubscribed,
    subscriberCount,
    subscribers,
    isLoading,
    toggle,
  } = useSubscription(resourceId, hash);

  return (
    <button onClick={toggle} disabled={isLoading}>
      {isSubscribed ? '★' : '☆'} {subscriberCount}
    </button>
  );
}

The hook returns:

| Field | Type | |---|---| | isSubscribed | boolean | | subscribers | SubscriberInfo[] | | subscriberCount | number | | isLoading | boolean (shared per resource — true while a refresh is in flight) | | subscribe() | () => Promise<void> | | unsubscribe() | () => Promise<void> | | toggle() | () => Promise<void> | | refresh() | () => Promise<void> |

Custom avatar rendering — renderSubscriber

Useful when subscribers' display name lives outside the Notifizz store (e.g. Clerk, Auth0):

import { useOrgMembers } from './clerk-helpers';

function ProjectSubscribe({ id, hash }: { id: string; hash: string }) {
  const { members } = useOrgMembers();

  return (
    <NotifizzSubscribe
      resourceId={id}
      hash={hash}
      renderSubscriber={(sub) => {
        const member = members.find((m) => m.userId === sub.id);
        return (
          <img
            src={member?.imageUrl}
            alt={member?.fullName}
            title={member?.fullName ?? sub.id}
            style={{ width: 28, height: 28, borderRadius: '50%' }}
          />
        );
      }}
    />
  );
}

By default, subscribers are rendered as colored circles with their initial (or avatarUrl if provided in the subscriber payload).

API

<NotifizzProvider>

| Prop | Required | Default | |---|---|---| | apiKey | ✅ | — | | mode | ✅ | — ('public' | 'secure') | | subscriberId | ✅ | — (typically the current user's email) | | apiUrl | | https://api.notifizz.com/v1 | | maxAvatars | | 5 |

<NotifizzSubscribe>

| Prop | Required | Notes | |---|---|---| | resourceId | ✅ | | | hash | If mode === 'secure' | HMAC hash for this (subscriberId, resourceId) pair | | renderSubscriber | | Custom avatar renderer (sub) => ReactNode | | subscribeLabel / unsubscribeLabel | | Override brand labels | | maxAvatars | | Override brand value | | className / style | | Wrap inline styles |

useSubscription(resourceId, hash?)

See "Custom UI" section above.

Lifecycle in SPAs

React handles lifecycle automatically — when a <NotifizzSubscribe> unmounts, the underlying subscription is cleaned up. No destroy() call needed.

If a parent re-renders with a new resourceId, the component re-subscribes to the new resource. State of the old resource stays in the module cache (other components on it remain in sync).

See also

  • @notifizz/subscribe-vanilla — JS/TS wrapper, multi-instance, framework-agnostic
  • @notifizz/subscribe-angular — Angular component
  • Documentation: https://docs.notifizz.com/sdks/subscribe (coming soon)