Laravel browser push notifications (no Firebase)
Laravel’s notification system already knows how to send mail and Slack messages. With the community WebPush channel, browser push becomes one more channel — using standard VAPID, no Firebase.
- Install laravel-notification-channels/webpush and run its migration.
- php artisan webpush:vapid writes VAPID keys into your .env.
- Add HasPushSubscriptions to your User model and save subscriptions from the browser.
- Return WebPushChannel from via() and build a WebPushMessage in toWebPush().
Install the channel
composer require laravel-notification-channels/webpush
php artisan vendor:publish --provider="NotificationChannels\WebPush\WebPushServiceProvider" --tag="migrations"
php artisan migrate
php artisan webpush:vapid # adds VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY to .envKeep the private key out of version control like any other secret (why).
Store subscriptions on users
use NotificationChannels\WebPush\HasPushSubscriptions;
class User extends Authenticatable
{
use Notifiable, HasPushSubscriptions;
}
// routes/web.php (inside your auth middleware group)
Route::post('/push/subscriptions', function (Request $request) {
$data = $request->validate([
'endpoint' => 'required|url',
'keys.p256dh' => 'required|string',
'keys.auth' => 'required|string',
]);
$request->user()->updatePushSubscription($data['endpoint'], $data['keys']['p256dh'], $data['keys']['auth']);
return response()->noContent(201);
});The browser code that creates the subscription is in the Push API example; pass your VAPID_PUBLIC_KEY to it.
A WebPush notification
use NotificationChannels\WebPush\WebPushChannel;
use NotificationChannels\WebPush\WebPushMessage;
class OrderShipped extends Notification
{
public function __construct(public Order $order) {}
public function via($notifiable) { return [WebPushChannel::class]; }
public function toWebPush($notifiable, $notification)
{
return (new WebPushMessage)
->title('Your order has shipped 📦')
->body('Arriving ' . $this->order->eta->format('l') . '. Tap to track it.')
->icon('/icon-192.png')
->data(['url' => route('orders.show', $this->order)]);
}
}
$user->notify(new OrderShipped($order));The service worker
Your public/sw.js needs push and notificationclick handlers that read the payload and open data.url. A complete version is in service worker push events. Make sure your web server and any CDN don’t cache it for long.
Queue it
Implement ShouldQueue on notifications so sending happens in a queue worker, not during the request. The channel removes subscriptions that the push service reports as expired.
The front-end subscribe call
// resources/js/push.js — call from a button click
const reg = await navigator.serviceWorker.register('/sw.js');
if (await Notification.requestPermission() === 'granted') {
const sub = await reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(window.VAPID_PUBLIC_KEY) // from config('webpush.vapid.public_key')
});
await fetch('/push/subscriptions', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content },
body: JSON.stringify(sub)
});
}Include the CSRF token because the route sits in the web middleware group. The urlBase64ToUint8Array helper is in the Push API example.
Unsubscribing and cleanup
When a user turns notifications off in your settings page, call subscription.unsubscribe() in the browser and $user->deletePushSubscription($endpoint) on the server. Expired endpoints (404/410 from the push service) should also be removed so your sends stay fast; check the package’s events and configuration for the version you install.
For marketing pushes, use a dashboard
The channel is perfect for per-user, transactional notifications. For marketing campaigns to anonymous visitors — segments, schedules, welcome automations — add Pusharoo’s snippet to your Blade layout instead; it’s free and needs no backend code (setup). Many apps use both.
Questions
Does Laravel have built-in browser push?
Not in the core framework. The community laravel-notification-channels/webpush package adds a WebPush channel using the standard protocol.
Can I send Laravel push notifications without Firebase?
Yes. The WebPush channel uses VAPID and the browsers’ own push services; no Firebase project is required.
Can guests (not logged in) receive Laravel push notifications?
The package stores subscriptions on a notifiable model, usually User. For anonymous visitors, store subscriptions on a guest model or use a hosted tool.
Keep reading
Web push notifications in PHP
Install with Composer, create VAPID keys, store subscriptions, queue and flush, remove expired endpoints.
The Web Push API in JavaScript: a working example
Register a worker, ask on click, subscribe with VAPID, store the subscription and send — complete code.
Service worker push events, done right
push and notificationclick handlers, focusing open tabs, action buttons, subscription changes and pitfalls.
VAPID keys for web push, explained
What the key pair does, how the signed JWT works, how to generate keys and why rotation breaks lists.
More in Developers: The Web Push protocol, explained · Web push notifications with Node.js · Web push notifications in React and Next.js · Declarative Web Push, explained · Firebase web push vs. standard web push · All guides
Free for life. No limits.
Unlimited subscribers, campaigns and automations. No badges. About five minutes to install.