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

@marcolabs/expo-push

v0.1.0-alpha.0

Published

Expo push notification runtime: permission lifecycle, device-scoped token management, badge sync, routing adapters, config plugin.

Readme

@marcolabs/expo-push

Expo push notification runtime — soft-ask permission lifecycle, device-scoped token management, badge sync, and a config plugin that opens the app's OS notification settings directly.

Install

pnpm add @marcolabs/expo-push
# peers: expo-application, expo-constants, expo-device, expo-notifications

app.json:

{ "plugins": ["@marcolabs/expo-push"] }

Plugin options (all optional):

{
  "plugins": [
    ["@marcolabs/expo-push", {
      "moduleName": "NotificationSettingsLink",
      "targetName": "MyApp",
      "androidPackage": "com.example.app.notificationsettings"
    }]
  ]
}
  • moduleName — JS-visible NativeModules key; pass the same value to createPushRuntime({ settingsNativeModuleName }).
  • targetName — iOS target name. Defaults to the sanitized Xcode project name (app names like "my-app" become "myapp"), so only set this for non-standard target names.
  • androidPackage — Java package for the generated Kotlin files (default: <android.package>.notificationsettings).

Runtime

import { createPushRuntime } from '@marcolabs/expo-push';

export const push = createPushRuntime({
  backend: {
    claimToken: (p) => api.claimPushToken(p),       // atomic per token
    releaseToken: (t) => api.releasePushToken(t),
    fetchUnreadCount: (uid) => api.unreadCount(uid),
  },
  storage: asyncStorageAdapter,
  reporter: { report: (e, ctx) => sentry.capture(e, ctx) },
});

Create once at app entry — it sets the foreground NotificationHandler.

Permission model (soft-ask)

  • requestPermission() — OS dialog; call only behind an explicit CTA (iOS won't re-show it after denial). Creates the Android channel FIRST — Android 13+ shows no popup without one.
  • syncTokenIfGranted(userId) — app-entry sync; never pops the dialog.

Token lifecycle

  • registerToken — 15s fetch timeout (iOS can hang forever without one), then backend.claimToken which must atomically re-assign a token still bound to another account.
  • clearToken — logout; releases THIS device's token while the session is still valid. Skipping this is how pushes leak across account switches.
  • addPushTokenListener — rotation on reinstall/OS updates.

Settings deep link

  • primeOSSettingsVisibility() — iOS registers the app in Settings > Notifications before you link there (reinstall edge case).
  • openNotificationSettings() — straight to this app's notification settings on both platforms, via the bundled config plugin's native module.

Listeners / badge

addNotificationListener, addNotificationResponseListener, getLastNotificationResponse + clearLastNotificationResponse, syncBadge(userId) (deduped per user while in flight).