naif/nova-push-notification
A Laravel Nova tool for composing and sending push notifications to users or devices from your admin panel, with Firebase Cloud Messaging support and a simple interface for managing notification delivery.
Install
composer require naif/nova-push-notifications
php artisan vendor:publish --provider="Naif\NovaPushNotifications\ToolServiceProvider"
Register the tool in app/Providers/NovaServiceProvider.php:
public function tools()
{
return [
new \Naif\NovaPushNotifications\NovaPushNotifications(),
];
}
Configure OneSignal in .env (consult the published config for exact key names — this package was written against the legacy OneSignal REST API v1):
ONESIGNAL_APP_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
ONESIGNAL_REST_API_KEY=your-rest-api-key
Then php artisan config:cache and php artisan nova:clear-cache if assets look stale.
Where to look first
config/nova-push-notifications.php — credentials, defaults, and any target options.src/ directory — find the controller/service that actually calls OneSignal. That's the code you'll end up wrapping or replacing.nova-push-notifications entry in the Nova sidebar after login — that's the compose form.First use case: send a one-off announcement to all subscribers from the Nova sidebar, then repeat the flow targeting a single device by its OneSignal player ID. This proves credentials, payload shape, and device registration all work before you build anything automated around it.
Admin-composed announcements (the package's sweet spot). Reserve the Nova tool for marketing/broadcast copy written by non-developers. Keep transactional copy in your codebase where it's versioned, reviewable, and testable.
Store the player ID on your user model. The tool can only target users it can identify. Add a nullable onesignal_player_id column (and index it) to users, populated by your app's OneSignal SDK on login/onSubscriptionChange. Without this, targeting is limited to "all users."
Wrap the send in a queued job. Don't let a controller or observer block a request on an external HTTP call. Extract the send call into a small action and dispatch it:
class SendPush implements ShouldQueue
{
use InteractsWithQueue, Queueable;
public function __construct(public $playerIds, public $title, public $body, public $data = []) {}
public function handle(PushNotifier $notifier)
{
$notifier->send($this->playerIds, $this->title, $this->body, $this->data);
}
}
Bind PushNotifier to a class in your own code — this is your escape hatch when the package stops working or OneSignal is swapped out.
Trigger pushes from domain events, not Nova. UserRegistered::class → welcome push; OrderShipped::class → tracking push. Listeners dispatch the queued job. This keeps the admin tool for humans and the event flow for the product.
Segment by collecting IDs, not by relying on OneSignal segments. Query users by role/team, pluck onesignal_player_id, chunk into ≤2000 per request (OneSignal's limit), and call include_player_ids. Segment definitions inside OneSignal drift out of sync with your database.
Use the data payload for routing. Include something like ['route' => 'orders/'.$order->id] and let the mobile app decide where to navigate. Don't encode deep-link logic in the notification body text.
If you need reliability, fork the send call. The package is small; copying its OneSignal call into a OneSignalNotifier class you own takes an afternoon and buys you retries, logging, and testability with Http::fake().
Version compatibility is the biggest risk. Last release March 2019 — this is Nova 2-era code. Nova 3/4/5 changed tool registration, NovaServiceProvider signatures, and asset publishing. Expect to fork and patch. Check the composer.json Nova constraint before installing into a modern project; composer require will tell you quickly.
The REST key is a loaded gun. The legacy OneSignal REST API Key can send to every subscriber on the app. Keep it in .env, never in the config file committed to git, and rotate immediately if it leaks. Newer OneSignal accounts use a different "App API Key" format — verify which yours is; the legacy key will 401 against a migrated app.
Config cache bites everyone. Editing .env and seeing no change in the tool means config:cache is holding the old values. Run php artisan config:clear in development.
OneSignal returns HTTP 200 with errors in the body. A 200 does not mean the notification was delivered. Inspect the errors array and the recipients count in the response; log both. Common silent failures: invalid player IDs, subscription opted out, wrong app_id.
Player IDs go stale. Devices reinstall, users revoke permission, OneSignal invalidates tokens. Prune onesignal_player_id when your app reports a new one, and treat low recipients counts as a data-hygiene signal rather than a mystery.
External user IDs require app-side setup. If you migrate to include_external_user_ids, those IDs must be set at OneSignal SDK initialization, not added after the fact. Existing registered devices won't have them until users update and re-register.
Large audience sends will time out in the Nova UI. The tool runs synchronously from an admin request. For anything above a few thousand devices, use the scheduled-send parameter or move the send into a queue. Otherwise admins see a 504 and the notification may have already gone out — send twice and you've annoyed everyone.
Test with a single device, not "All". Develop against one real player ID from a test device. There's no undo on a broadcast.
Debugging: Log the full OneSignal request and response JSON around the send call. The Nova tool gives you almost no error surface — most failures show as a generic flash message or a silent no-op.
Extension points worth knowing: publish and override the tool's views (vendor:publish --tag=views, verify tag name in the service provider), and bind your own notifier implementation rather than editing vendor code. If the package's controller is doing the HTTP call directly, subclass or replace it in your Nova service provider's tools() array.
Given 16 stars and a 2019 release, treat this as reference code rather than a dependency you can rely on for maintenance. Read its OneSignal call, port it into your own notifier, uninstall, and keep the Nova UI if you still want an admin compose screen.
How can I help you explore Laravel packages today?