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

@mint-soft/notikit-web

v0.2.0

Published

Notikit Web SDK — browser push via FCM (Firebase Cloud Messaging)

Readme

@mint-soft/notikit-web

Notikit Web SDK — 브라우저 푸시 (FCM / Firebase Cloud Messaging).

토큰은 FCM 등록 토큰입니다. 서버는 안드로이드·iOS 와 같은 경로로 발송하므로 웹 전용 전송 분기가 필요 없습니다.

설치

npm install @mint-soft/notikit-web firebase

firebase 는 peer dependency 입니다(선택). getToken 을 직접 넘기면 설치하지 않아도 됩니다.

1) 서비스워커 배치

public/notikit-sw.js 로 SDK 의 NOTIKIT_SERVICE_WORKER 문자열을 그대로 저장하세요.

import { NOTIKIT_SERVICE_WORKER } from "@mint-soft/notikit-web";
// 빌드 스크립트에서: fs.writeFileSync("public/notikit-sw.js", NOTIKIT_SERVICE_WORKER)

워커는 설정을 자기 URL 쿼리에서만 읽습니다(워커에는 SDK 인스턴스가 없습니다). register() 가 쿼리를 자동으로 붙이므로 경로만 맞추면 됩니다.

2) 등록

firebase 설정은 항상 필요합니다. 워커에는 앱의 Firebase 인스턴스가 없어서, 이 값으로 직접 초기화해야 백그라운드 메시지를 받습니다.

import { NotikitWeb } from "@mint-soft/notikit-web";

const notikit = new NotikitWeb({
  baseUrl: "https://push.example.com",
  apiKey: "nk_xxx",
  vapidPublicKey: "B...",   // Firebase 콘솔 > 클라우드 메시징 > 웹 푸시 인증서
  userId: "user-123",       // 고객 서비스의 유저 id (서버에는 user_id 로 전송)
  firebase: {
    apiKey: "AIza...",
    projectId: "my-project",
    messagingSenderId: "1234567890",
    appId: "1:1234567890:web:abc",
  },
  // 워커가 불러올 compat SDK 버전. 설치한 firebase 와 메이저를 맞추세요.
  firebaseSdkVersion: "12.0.0",
});

if (NotikitWeb.isSupported()) {
  await notikit.register(); // 권한 요청 → FCM 토큰 → 서버 등록
}

userId 는 고객 서비스의 유저 id 이며 서버에 user_id 로 보냅니다. 이전 이름 externalId(external_id)도 그대로 동작하지만 deprecated 입니다 — 둘 다 주면 userId 가 이깁니다. identify(userId, attributes?, name?) 도 같습니다.

이미 Firebase 를 초기화한 앱이라면 토큰 획득만 넘겨받게 할 수 있습니다 — SDK 가 initializeApp 을 또 부르면 앱이 쓰던 인스턴스와 어긋납니다. (firebase 설정은 그래도 워커용으로 함께 넘겨야 합니다.)

import { getMessaging, getToken } from "firebase/messaging";

const notikit = new NotikitWeb({
  /* ...위와 동일... */
  getToken: (reg) =>
    getToken(getMessaging(myFirebaseApp), { vapidKey: "B...", serviceWorkerRegistration: reg }),
});

3) 토큰 교체

FCM 은 토큰을 갱신합니다. 새 토큰으로 register() 를 다시 부르면 행이 하나 더 생겨 같은 사람에게 중복 발송됩니다. 교체는 전용 메서드를 쓰세요 — 서버가 기존 행을 제자리 갱신해 토픽 구독·클릭 이력이 보존됩니다.

웹에는 토큰 갱신 이벤트가 없습니다. 네이티브의 onNewToken/didReceiveRegistrationToken 에 해당하는 것이 모듈 API(v10~v12)에 없으므로, 앱이 직접 비교해야 합니다. 앱을 열 때 한 번 확인하는 정도면 충분합니다 — FCM 토큰은 수명이 깁니다.

const saved = localStorage.getItem("fcm_token");
const current = await getToken(getMessaging(app), { vapidKey, serviceWorkerRegistration: reg });

if (saved && current && saved !== current) {
  await notikit.rotateToken(saved, current);
}
localStorage.setItem("fcm_token", current);

서버가 옛 토큰을 찾지 못하거나 증명이 맞지 않아 교체하지 못하면(rotated: false), SDK 가 새 토큰을 현재 userId·identityHash 로 직접 등록합니다. 그것마저 실패하면 던지므로 저장한 토큰을 갱신하지 말고 다음에 다시 시도하세요(위 예제는 던지면 setItem 까지 가지 않습니다).

클릭 추적

워커가 notificationclick 에서 자동으로 보고합니다. 탭이 보이는 상태(포그라운드)에서 온 푸시도 onForegroundMessage 를 넘기지 않았다면 SDK 가 서비스워커 등록으로 같은 모양의 알림을 띄우므로 클릭은 같은 경로로 보고됩니다(무음 푸시는 띄우지 않습니다). 보고에 쓸 FCM 토큰은 등록 시점에 IndexedDB 에 저장된 값을 읽습니다 — 워커에서는 getToken 을 부를 수 없기 때문입니다.

수신(도달) 추적

워커가 push 이벤트에서 자동으로 보고합니다(POST /api/v1/messages/received). 앱 코드는 아무것도 하지 않아도 됩니다 — 워커만 최신 NOTIKIT_SERVICE_WORKER 로 배치하세요.

notificationclick 이 아니라 push 에 다는 이유: 무음(data-only) 푸시는 알림을 띄우지 않고, 사용자가 알림을 누르지 않는 경우가 대부분입니다. push 는 배달된 모든 메시지에 대해 한 번 뜨므로 "받았다"의 정의와 정확히 겹칩니다.

이 보고가 없으면 콘솔의 "도달" 칸은 계속 비어 있습니다 — 발송 성공(FCM 접수)은 기기가 꺼져 있어도 성공하므로 도달이 아닙니다. 같은 워커 인스턴스 안에서 같은 발송이 다시 배달되면 요청을 내보내지 않고, 서버도 (발송, 기기) 유니크로 한 번만 셉니다.

iOS Safari 는 홈화면에 추가한 PWA 에서만 웹 푸시가 동작합니다(16.4+).

라이선스

Apache-2.0