Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Apn Laravel Package

laravel-notification-channels/apn

Send push notifications to iOS, macOS, and watchOS from Laravel using Apple's APN service. This notification channel supports token and certificate authentication, HTTP/2, custom payloads, and easy integration with Laravel's notification system.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Build vs. buy for iOS/macOS push delivery. Shipping APNs means owning HTTP/2 transport, .p8 provider-token minting, JWT signing, refresh cadence, and Apple's throttling rules. This package reduces that to a toApn() method on a notification class the team already writes. A sprint of specialized, permanently-owned infrastructure becomes an MIT dependency you can staff behind.
  • Roadmap sequencing for notification features. Transactional alerts (order shipped, payment failed, security event), badge hygiene, and re-engagement nudges stop being an infrastructure project and become payload work. Push can land inside an existing notification epic next to mail, database, and SMS rather than gating a release on a new subsystem.
  • Laravel 13 upgrade planning. v6.4.0 exists specifically because the prior design—caching the whole APN client object—clashed with Laravel 13's stricter cache controls. Scope this as a concrete unblocker in the upgrade, not a cosmetic version bump; it is a line item with a real dependency behind it.
  • Reliability and cost posture at volume. The provider token is cached for 20 minutes with automatic replacement, matching Apple's regeneration guidance and cutting auth round-trips plus 429 TooManyProviderTokenUpdates risk. That is the throughput argument for adopting this over a hand-rolled integration that mints a token per send.
  • Security sign-off. The previous behavior serialized a credential-bearing HTTP client into the cache backend. v6.4.0 stops doing that, removing Apple credentials from the cache store. Cite this explicitly in review; it's a defensible answer to "where do credentials live?"
  • Multi-app and multi-environment architecture. Token-based (.p8) and certificate auth, plus sandbox/production endpoints, matter if the product ships a family of iOS apps or a stage/prod split. Decide this early—retrofitting per-app credentials after the token cache is in play is a known source of intermittent 403 InvalidProviderToken bugs.
  • Explicit non-decision. This is not a marketing automation or campaign platform. It sends pushes; it does not segment, orchestrate, A/B test, suppress, or report. Draw that boundary in the PRD now, because "while we're here, can we add…" is how a channel package gets asked to become Braze.

When to Consider This Package

Adopt when:

  • The backend is Laravel/PHP and push is being added to a notification flow that already exists—you want it in via()/toApn() beside channels you already run.
  • Volume is meaningful enough that provider-token reuse actually matters: queued fan-out, batch sends, bursty alerting.
  • You want to avoid owning APNs token lifecycle and Apple's "don't regenerate more than once every 20 minutes" guidance.
  • You are on, or moving to, Laravel 13 and need cache behavior that complies with stricter cache controls.
  • Scope is transactional and alert-style push to known device tokens—not audience discovery or campaign management.
  • A shared cache store (Redis/Memcached/database) is provisioned or can be. Single-node file cache gives correctness but forfeits most of the caching benefit.

Look elsewhere / reconsider when:

  • The requirement is campaign management, segmentation, analytics, cross-platform orchestration, or send-time optimization. That is a push vendor (OneSignal/Airship/Bravo-class), not a Laravel channel. Buy there; do not let this package absorb that scope.
  • You are not on Laravel/PHP. The entire value here is framework integration; a dedicated provider is the honest comparison.
  • No shared cache store is planned and you expect high volume—the 20-minute token reuse is the main operational win.
  • Credential rotation runbooks don't exist. Rotating the .p8 or Key ID without flushing the token cache leaves a ~20-minute stale window where a revoked key still works.
  • Your team cannot absorb self-support. This is 201 stars, zero dependents, effectively one maintainer. It is reasonable for notification-critical paths if you pin ^6.4, keep the channel behind your own notification abstraction, and know what you'd do if it went unmaintained. If vendor SLAs are a procurement requirement, this fails that test.
  • Device-token governance is unsolved. Real apps outgrow a single users.device_token column within a sprint—multiple devices, reinstalls, iPad + iPhone. If there's no plan for a device-token table and a Unregistered/BadDeviceToken cleanup path, the feature ships broken and stays broken.

How to Pitch It (Stakeholders)

To executives: Native iOS and macOS push can ship inside our existing notification system instead of as a standalone infrastructure project. That converts a multi-week, specialist-owned build into a dependency plus payload work, and it slots into a roadmap we already have rather than adding a new one. The recent release also fixes how Apple credentials are handled—they no longer sit in our cache store, and the auth token is now reused for 20 minutes the way Apple intends, which is both a security and a scale story. The trade-off to accept consciously: this is a small open-source package with essentially one maintainer, so we treat it as self-supported, keep it behind our own abstraction, and pin the version. It sends notifications. It does not run campaigns, segment audiences, or report on delivery—if we want that, it's a separate buy decision.

To engineering: It's an idiomatic Laravel notification channel—ApnChannel in via(), toApn() returning an ApnMessage, config published from the provider. Supports .p8 JWT and certificate auth, bundle ID as apns-topic, sandbox/prod switch. Queue it by default with its own queue and a worker timeout under your retry_after; resolve the client from the container so the 20-minute token cache is actually shared. Handle CouldNotSendNotification in failed(): soft-delete token rows on Unregistered/BadDeviceToken and don't retry, back off on 429/503/TooManyProviderTokenUpdates. Beware env() outside config/apn.php under config:cache, store the .p8 as a file path with intact BEGIN/END lines and trailing newline, and don't hit Apple in tests—Notification::fake() plus one real sandbox device check.

To security/review: Credentials have moved out of the cache backend, and the .p8 lives outside the webroot, referenced by path rather than inlined in env. Rotation is a runbook step: rotate the key and flush the token cache in the same change, or the old key stays live for the TTL window.

To the iOS team: Categories must match UNNotificationCategory registrations in-app; deep-link identifiers go in the custom payload, not stuffed into body. Treat silent/data-only pushes (contentAvailable) as best-effort—iOS budgets them and drops them under low power, so nothing the app depends on should ride on them alone. And "sent successfully" is not "shown": permission denial and Focus mode are invisible to the server. The apns-id we set is for log correlation, not proof of delivery—don't let product logic assume otherwise.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox