Notification Kit โ a project by Ahsan Mahmood
Zero-runtime-dependency TypeScript library that unifies push, local, and in-app notifications behind one provider-less API for React and Capacitor apps.
Three separate things get called a notification and only one of them involves a server.
A push arrives while the application is closed and travels through a vendor. A local notification is scheduled on the device itself and fires whether or not anything is reachable. An in-app message is a piece of interface, and calling it a notification at all is mostly habit.
Three mechanisms wearing one word.
Which is why this work is always larger than the ticket that requested it. A team wires Firebase for push, a Capacitor plugin for local, a toast component for in-app, then three separate permission stories, then a service worker whose lifecycle nobody enjoys learning.
Notification Kit puts one API over all three.
Schedule a local notification. Show an in-app message. Get a push token. The same shape each time, with optional React hooks for the places where a hook is genuinely easier than a function call.
Zero required dependencies is the decision underneath that.
The core works the moment it is installed. A provider SDK loads dynamically only when that provider is enabled, so a project that schedules local reminders and nothing else never downloads a push vendor, and adding push a year later is configuration rather than surgery.
The details that make it usable are the ones nobody writes on a roadmap.
Android notification channels, because a channel the user silenced swallows a notification without raising an error anywhere. Rich media. A fluent way to say every weekday at eight. Service-worker templates, since the worker is where most web push integrations quietly come apart.
A service worker is not a background process you own.
The browser starts it, stops it and starts it again on its own schedule, so anything written on the assumption that it stays alive between two events is a bug waiting for a slow morning and a cold cache.
Then there is a boundary worth stating in a page like this.
A reminder your product schedules for one user is a local notification. It is not a push. Treating it as one buys a vendor, a permission prompt and a delivery chain that the feature never needed, and that single confusion is what turns a two-day job into a fortnight.
What it cost was 124 tests, a dual ESM and CommonJS build, full type declarations, a setup CLI and a written integration guide aimed at coding agents rather than people.
An integration guide written for coding agents is a strange artefact to produce. It exists because the thing wiring a package into a codebase is increasingly not a person reading a README, so the guide is written for that reader rather than bolted on as decoration.
The standing cost is delivery, and it is not mine.
Push depends on a vendor, on a platform's power management and on a permission the user can revoke without telling anyone. An honest library reports what it knows and declines to claim what it cannot observe, which means there is no delivery guarantee here and there was never going to be one.
There is no iOS release behind this work, because there is no Apple Developer account here.
It is on npm as notification-kit, with the source at github.com/aoneahsan/notification-kit.
Getting a token is easy. What your product does on the morning that token stops working is the actual feature, and it is the part a notification library can help with only if it was honest about the rest.
What it does, and what that costs to build
- One API for push, local & in-app notifications
- Zero runtime dependencies (all peers optional)
- Provider-less React hooks (no context wrapper)
- Fluent recurring local-notification scheduling
- Android notification channels + rich media
- Service-worker templates + setup CLI
- Dual ESM + CJS packaging
Built with
- TypeScript
- Vite 8
- React 19
- CapacitorJS
- Firebase
- OneSignal
Worth knowing
- npm
- package
- notifications
- react
- capacitor
- zero-dependency
Who built Notification Kit?
Ahsan Mahmood built and published it, including the setup CLI and the written integration guide for coding agents. It is on npm as notification-kit, with the source at github.com/aoneahsan/notification-kit. A package like this only exists because the same person had already wired push, local notifications and in-app messaging separately in several products, and the third time through is when a pattern becomes obvious enough to be worth extracting. The pieces that survived that extraction are the ones that had broken in real use rather than the ones that looked tidy.
What does zero dependencies mean if it talks to Firebase and OneSignal?
It means those vendor SDKs are not installed with the package and are not in your bundle until a provider is switched on. The core is self-contained and works the moment it is installed; a provider SDK loads dynamically at the point a project actually enables it. So a product that only schedules local reminders never downloads a push vendor, and a product that adds push a year later restructures nothing to get it. The peers stay optional in both directions, which is why the package can sit in a small project without dominating it.
Does Notification Kit work on iPhone?
No. There is no Apple Developer account behind this work, so nothing here has shipped to the App Store, and web and Android are the two surfaces the push path has actually been exercised on. The in-app half is a different matter, because in-app messaging is ordinary interface code and runs wherever your application runs, an iPhone browser included. What you should not read into that is any claim about push delivery on an Apple device, which is untested here and stays untested until an account exists.
Does it handle the permission prompt and Android channels?
Yes, and the channel half matters more than it looks. On Android every notification belongs to a channel, and a channel the user has silenced swallows the notification without raising an error anywhere, so a library that ignores channels hands you a bug your own logs cannot see. Permission is asked behind a user action rather than on first load, because a prompt fired at a stranger is a prompt denied permanently. Rich media and a fluent way to express a recurring local schedule live in the same layer.
When should I use a local notification instead of push?
Whenever the reminder belongs to one user and your server has nothing to add to it. A daily nudge, a timer, a scheduled check-in: each of those is a local notification, scheduled on the device, firing whether or not a network is there. Treating them as push buys a vendor, a delivery chain and a permission conversation none of them needed. Push earns its place when the event starts somewhere other than the device, which is a narrower set of cases than most product plans assume at the outset.
https://aoneahsan.com/projects/com.aoneahsan.notificationkit