
Product
Socket for Asana Is Now Available
Create and manage Asana tasks directly from Socket alerts, with manual task creation, automated ticketing rules, and two-way sync.
@notiflyio/capacitor-push
Advanced tools
Capacitor plugin wiring Notifly push into PWA shell apps: FCM channel setup, injected window-event bridge, and same-origin notification deep links
Capacitor plugin wiring Notifly push into the fleet's PWA shell apps. It owns what every shell used to hand-copy (caly-pwa-android / marka-pwa-android#5, ~350 lines per app):
bridge/notifly-push-bridge.js) installed
at document start into every document of the app origin, re-dispatching
@capacitor/push-notifications activity as the SAME window CustomEvents the
fleet's raw-WKWebView iOS shells emit — the app's web layer keeps one set of
listeners, no per-platform fork.references/contracts.md)One token event on both platforms, naming its own provider — a web layer keeps one listener and never forks per platform.
| Direction | Name | Detail |
|---|---|---|
| shell → web | push-apns-token | { token: string, provider: 'apns' | 'fcm' } |
| shell → web | push-apns-error | error message string |
| shell → web | push-notification | foreground payload (title, body, link, data) |
| shell → web | push-permission-request | 'granted' | 'denied' |
| shell → web | push-permission-state | 'authorized' | 'denied' | 'notDetermined' |
| web → shell | window.NotiflyPush.requestPermission() / permissionState() / token() | control object (plus the jsGlobal alias) |
| web → shell | window.webkit.messageHandlers['push-permission-request' | 'push-permission-state' | 'push-token'].postMessage('') | same three calls, under the names the fleet's raw-WKWebView shells register |
| Name | Detail | Status |
|---|---|---|
push-fcm-token | device token string | Android only; emitted alongside push-apns-token. Deprecated — read the primary event's provider instead. |
push-fcm-error | error message string | Android only; emitted alongside push-apns-error. Deprecated. |
Both aliases keep 0.1.0's bare-string detail, so a consumer written against
0.1.0 needs no change. They will not be removed before 1.0. On iOS the legacy
name and the primary name are the same event, so it is dispatched exactly once,
with the object detail.
Migration for a 0.1.0 consumer: read the token from push-apns-token, accepting
either shape —
const read = (detail) => (typeof detail === 'string' ? { token: detail, provider: 'apns' } : detail);
window.addEventListener('push-apns-token', (e) => { const { token, provider } = read(e.detail); ... });
— and drop the push-fcm-* listeners.
The control object appears asynchronously: the injected script retries for
~10s until Capacitor's runtime is callable (a server.url shell has not
bootstrapped it at document start), then warns [notifly] gave up installing the push bridge if it never was. Probe for window.NotiflyPush when you need it,
not once at mount.
npm install @notiflyio/capacitor-push @capacitor/push-notifications
npx cap sync
@capacitor/push-notifications is a peer dependency and LOAD-BEARING beyond
gradle wiring: Capacitor's own JS export writes
Capacitor.Plugins.PushNotifications (the probe web layers use to detect the
native push leg) only when that plugin is installed.
{
"plugins": {
"NotiflyPush": {
"jsGlobal": "MarkaPush",
"channelId": "marka_default",
"channelName": "Marka notifications",
"channelDescription": "General notifications",
"allowedHost": "joinmarka.com"
}
}
}
All keys optional — channelId defaults to notifly_default, the canonical
window.NotiflyPush global is always set, deep links always allow the app
origin (server.url).
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="marka_default" />
plus the usual Firebase leg: google-services.json in android/app/ and the
com.google.gms.google-services gradle plugin. Firebase project MUST be the
app's existing OAuth GCP project (SenderId-mismatch class — see the
pwa-notifications skill's portal-setup reference).
The initial page load is already in flight during plugin load, so a cold-start tap must steer that load from the activity:
import io.notifly.capacitorpush.NotiflyPushBridge;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String link = NotiflyPushBridge.deepLinkFrom(getIntent(), getBridge().getConfig().getServerUrl());
if (link != null) {
getBridge().getWebView().loadUrl(link);
}
}
Warm taps (app already running) are handled by the plugin's handleOnNewIntent
— no activity code. If your activity ALSO navigates on new intents, both
navigations target the same URL (harmless).
The app-side token relay route (session-authed, forwards the device token
to Notifly's per-device endpoints) deliberately stays app-side too — it needs
the app's auth. Recipe: pwa-notifications references/wiring.md.
bridge/notifly-push-bridge.js is the canonical script; pnpm build (or
node scripts/embed-bridge.mjs) stamps it into the committed native copies
(android/src/main/assets/ + generated BridgeScript.swift).
node scripts/embed-bridge.mjs --check gates drift (runs in prepublish).
pnpm test runs test/bridge.test.mjs — the real script in a fake document
(node:vm, fake clock), pinning the install retry and the event contract. Both
also run on every PR (.github/workflows/ci.yml). Point NOTIFLY_BRIDGE_PATH at
another copy of the script to run the suite against it: with 0.1.0's bridge, 9
of the 13 checks fail, starting with the install race (notifly#61).
marka_default channel created from config, and the injected bridge's
addListener → checkPermissions → register → FCM registration event with no
registrationError. Remaining before 1.x: a real notification DELIVERY + tap
deep-link pass on a physical device.
0.1.1 cures what the superbooks Android device proof found on 2026-08-01
(notifly#61): on that shell the bridge never installed on any page of the app
origin, because at document start on a fresh server.url context Capacitor is
not callable yet and 0.1.0 returned for good. The install is now self-retrying
and test/bridge.test.mjs pins it.FAQs
Capacitor plugin wiring Notifly push into PWA shell apps: FCM channel setup, injected window-event bridge, and same-origin notification deep links
The npm package @notiflyio/capacitor-push receives a total of 24 weekly downloads. As such, @notiflyio/capacitor-push popularity was classified as not popular.
We found that @notiflyio/capacitor-push demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Product
Create and manage Asana tasks directly from Socket alerts, with manual task creation, automated ticketing rules, and two-way sync.

Security News
Open VSX has removed three extension IDs from its malicious-extension list as the legitimate publishers they impersonated move to claim the names for themselves.

Product
Socket’s PHP and Composer support is now in Beta for all customers, with PHP reachability analysis generally available.