amjadiqbal/laravel-webpush-kit
A Laravel package for sending Web Push notifications to browsers, with helpers for managing push subscriptions and VAPID keys. Adds push support to your app without building the underlying flow yourself.
Architecture fit. This is the browser half that laravel-notification-channels/webpush deliberately left to the application: subscription button, service worker, subscription routes, and iOS Home Screen plumbing. It is Laravel-native rather than a JavaScript SDK wrapper — a Blade component, an artisan command, publishable assets, an about entry — which means it inherits your existing auth, routing, and asset pipeline instead of introducing a parallel front-end stack. Critically, it does not create a second source of truth for subscriptions: the routes delegate to the channel's own updatePushSubscription() / deletePushSubscription(). That is the single most important architectural property here and it is satisfied.
Integration feasibility. Low-to-moderate. composer require, publish the service worker (or import it into an existing one), drop <x-webpush-kit::head /> and <x-webpush-kit::button /> onto a page, reuse the VAPID keys the channel already requires. No new infrastructure, no new credentials, no queue or scheduler changes.
Technical risk.
| Risk | Severity | Note |
|---|---|---|
Pre-1.0 (v0.1.0) |
High | No semver stability guarantee; assume breaking changes in 0.x minors. Pin exactly. |
| Untested click handling | High | The click target is set and inspected, but a real notification click was never exercised. This is the primary user action of the feature. |
| Firefox / Safari macOS / iOS Home Screen untested | High | Covers a large share of the addressable audience; the package claims to handle these states but has not proven it on-device. |
| Service worker scope collision | Medium-High | A fixed /webpush-sw.js competes with any existing worker. "Importable into your own" is the escape hatch — confirm the import path preserves pushsubscriptionchange re-subscribe logic. |
| Route authorization | Medium | Save/delete/rotate endpoints must be behind auth + CSRF + rate limiting; verify a user cannot delete another user's subscription. |
| Version floor | Medium | PHP 8.3+, Laravel 12/13 only. Excludes Laravel 10/11 and PHP 8.2 apps outright. |
Key questions.
skipWaiting / clients.claim)? Stale workers are the most common "push stopped working" cause.webpush-kit:subscribed fires but the server-side save fails?Stack fit. Laravel 12/13, PHP 8.3+, channel v11–13. Fits if your app is already on the channel — this is an additive front-end layer, not a replacement. If you are not already sending web push server-side, this package is not the entry point; adopt the channel first.
Migration path.
/webpush-sw.js, register as-is. Simplest path.pushsubscriptionchange survive the merge.webpush-kit:subscribed / webpush-kit:unsubscribed into your existing analytics first so you don't lose instrumentation continuity.Compatibility. Chrome/Edge desktop verified against Google's push service, including a real 410 dead-endpoint path. Firefox, Safari macOS, and iOS Home Screen are unverified. iOS additionally requires 16.4+ and Add to Home Screen — the component surfaces this state, but the degradation path has not been exercised.
Sequencing.
php artisan push:test against a staging device.Maintenance. Pre-1.0 means you own upgrade churn: pin the exact version, read every changelog, and budget for breaking changes on each 0.x bump. You also inherit the channel's version coupling and the PHP 8.3 / Laravel 12 floor, which will gate your own upgrade calendar rather than the reverse.
Support. php artisan push:test and the about entry are genuine support-cost reducers — they turn "push is broken" into a per-service answer (including 404/410 dead subscriptions and the Safari VAPID_SUBJECT rejection) in one command instead of a log dive. Offset against that: the untested browsers mean first-line support will field Firefox and Safari tickets with no verified baseline to compare against.
Scaling. The package adds no server-side fan-out; delivery scales with the channel and the push services. The routes do a per-request database write, and pushsubscriptionchange can trigger re-subscribe churn — rate-limit the endpoints and watch write volume on large subscriber bases.
Failure modes to expect.
push:test.VAPID_SUBJECT — warned about, but a config error that fails silently on other browsers.Ramp-up. Low for a Laravel team: one component, one command, one publishable asset. The real cost is not learning the API, it is owning browser-permission UX and service worker lifecycle — assign a named owner for that, because it is where the incidents will come from.
Recommendation. Adopt for a flagged pilot to validate the untested paths, not as a GA dependency at 0.1.0. Promote to GA once notification click, Firefox, Safari macOS, and iOS Home Screen are verified — or once the package reaches 1.0 with a stated support window.
How can I help you explore Laravel packages today?