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

Mercure Laravel Package

symfony/mercure

Symfony Mercure is the PHP publisher component for the Mercure protocol, letting you push real-time updates from your app to browsers and HTTP clients. It handles JWT authentication and dispatching updates to a Mercure hub.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Build vs. buy vs. adopt for real-time features. This is still the cheapest credible "adopt" option if the roadmap contains server-to-client push: live order/status tracking, notification bells, live dashboards, activity feeds, collaborative cursors, or long-running job progress bars. It replaces a custom WebSocket service or a third-party SaaS (Pusher, Ably, Firebase) with an MIT-licensed, standards-based protocol you can self-host or point at any Mercure hub. As of v0.9.0 the package defaults to Mercure protocol 1.0, which is now a stable, released standard — the "adopt a protocol, not a vendor" argument is materially stronger than it was at v0.7.
  • De-risking the roadmap with a protocol, not a vendor. Mercure 1.0 having shipped and stabilized removes the biggest prior objection ("we'd be adopting a draft standard"). You can switch hubs or self-host without rewriting application code, so "real-time" is a reversible bet rather than a platform commitment — which matters for a 12–24 month roadmap.
  • Feature prioritization: unidirectional push vs. full duplex. The package still covers the publisher half only: server → browser over SSE/HTTP. It is the right primitive for ~80% of "real-time" asks (notifications, feeds, status, progress). It is the wrong primitive for chat presence, typing indicators, multiplayer, or anything needing client → server streaming. This distinction remains the single biggest scoping decision the package forces, and it should be made before committing a quarter.
  • Architecture direction: event-driven internal design. Publishing is a single call from a Laravel event listener or queued job, so it layers onto the events/queues the team already has. It also creates a forcing function to standardize topic naming (e.g. /users/{id}, /orders/{id}), which pays off later in permissions and fan-out control. Worth noting the new default cookie name (__Secure-mercure_access_token) and the match query parameter — decide these once, in a shared config, before frontend work fans out.
  • Monetization / tiering decisions. Authorization is still JWT-scoped per topic, so you can gate premium real-time features (live inventory, multi-user sync) behind plans and entitle them in the token. Action item from v0.9.0: the LcobucciFactory claims model changed to authorization_details and now requires iss, aud, sub and client_id. If entitlement logic was ever sketched against the old claim shape, re-spec it now — this is the piece most likely to be mis-scoped by whoever implements it.
  • Cost modeling against SaaS alternatives. Self-hosted hub = fixed infra cost; managed hub = usage-based. The FrankenPHP hub option is now more attractive operationally (v0.9.0 makes its failure mode a clear, explanatory exception rather than a "call to undefined function" crash), meaning a team already serving via FrankenPHP can potentially avoid standing up a separate hub service. The PM should still model updates/month against Pusher/Ably pricing before choosing — at low volume SaaS usually wins on total cost of ownership.
  • Release and upgrade policy as a planning input. v0.9.0 is a breaking release for anyone on a 0.x hub: the default protocol flips to 1.0, the cookie name changes, the Twig helper's query parameter becomes match, and the JWT claim shape changes. That is a coordinated deploy — hub upgrade, package upgrade, token issuance change, and frontend cookie/query-param change must land together, or auth silently breaks. Budget it as a milestone, not a composer update. It also signals the package is converging on 1.0, so pinning versions and planning a maintenance ticket per upgrade cycle continues to be the right posture.
  • Security and rotation posture. The addition of a fully-specified Ed25519 algorithm in WebTokenFactory (as EdDSA is deprecated in the underlying JWT library) is a small but real governance win: specify Ed25519 in your key-rotation runbook now rather than inheriting a deprecated polymorphic algorithm.
  • Fallback and reliability policy. Mercure clients reconnect automatically and support Last-Event-ID replay, so "what happens when real-time breaks" becomes a documented degradation (fall back to polling) rather than a support fire.

Realistic evidence base for these decisions: MIT license, Symfony-maintained, active compatibility releases through PHP 8.5 / Symfony 8, now on stable Mercure protocol 1.0 by default — but still pre-1.0 (v0.9.x) with a modest footprint and effectively zero registered downstream dependents, meaning no Laravel-native ecosystem, no drop-in package, and you own the glue code, plus the hub/package protocol versions must be kept in lockstep.

When to Consider This Package

Adopt when:

  • The primary need is server → client push (notifications, status changes, live counters, progress, feeds) and latency of sub-second-ish is enough.
  • The team is PHP-centric and already comfortable with Laravel events, queues, and HTTP clients; SSE on the frontend is a few lines of EventSource, no new JS framework.
  • Vendor neutrality is a stated requirement (procurement, data residency, regulated sector) — MIT + a now-stable protocol 1.0 beats a proprietary SaaS socket service, and beats a draft spec.
  • You want auth to reuse existing identity: Mercure's JWT authorization model maps onto Laravel users, roles, and tenancy via per-topic subscribe/publish claims — with the caveat that you must now supply iss, aud, sub and client_id for the authorization_details factory, which means deciding your issuer/audience/client-id values up front.
  • You are operating a Mercure 1.0 hub (or are willing to upgrade to one), and you can treat package and hub as a paired version set.
  • Real-time is an enhancement, not the core product. Progressive enhancement over existing REST endpoints keeps blast radius small.

Look elsewhere when:

  • You need bidirectional or sub-100ms interactive traffic (chat, presence, collaborative editing with conflict resolution, games). Use WebSockets — and note Laravel Reverb is first-party, so the build-vs-buy math favors it heavily for Laravel shops.
  • You are already on Laravel Echo + Pusher/Reverb. Adding Mercure means a second transport, a second auth model, and two client libraries. Consolidate instead.
  • Nobody will own a hub (self-hosted Caddy/FrankenPHP service, or a managed subscription, plus key rotation and TLS). Real-time infra without an owner becomes a pager at 2 a.m.
  • Your hub can't move to protocol 1.0 in the same window as the package upgrade — staying on a 0.x hub means pinning to ProtocolVersion::Legacy and carrying a legacy config path you did not design for. Don't straddle versions across environments.
  • You need guaranteed delivery / auditability. Mercure is best-effort with reconnect and replay windows; durable, ordered, exactly-once delivery belongs in a queue or event store.
  • Your client fleet can't do SSE (some legacy or restricted corporate networks/proxies buffer event streams). Validate on the actual customer base before committing.
  • The app is not PHP (Node, Go, mobile-first backends) — the publisher exists elsewhere; don't adopt this just for familiarity.
  • You are not prepared for pre-1.0 churn. This release is the proof: a single minor version changes cookie names, query parameter names, and JWT claim shape. Pin versions, read every changelog, and budget a maintenance ticket per upgrade cycle.

How to Pitch It (Stakeholders)

To executives (1 minute): "We can ship real-time updates — live order tracking, instant notifications, live dashboards — without building or buying a proprietary messaging platform. This is an MIT-licensed, Symfony-maintained component on an open standard that just reached a stable 1.0: no vendor lock-in, no per-message SaaS bill, and it plugs into the Laravel stack we already run. Version 0.9.0 is the maturity signal we were waiting for — it defaults to the stable protocol and tightens signing with a modern algorithm. The tradeoffs are unchanged: it's a server-to-user push channel only, not two-way chat; it still needs an owned hub service; and it's pre-1.0, so upgrades are planned work, not automatic. Recommendation: pilot on one notification feature next sprint against polling, and fold the hub upgrade into the same milestone since the release requires the hub and package to move together."

To engineering (the honest version):

  • What it is: the publisher side of the Mercure protocol — one publish() call sends a named update to a topic; clients subscribe over SSE. Hub is separate (self-hosted Caddy/FrankenPHP, or managed). As of v0.9.0 the default is protocol 1.0, so your hub must be 1.0; pass ProtocolVersion::Legacy only as a deliberate, time-boxed bridge to a 0.x hub.
  • Why it fits: publishes from a Laravel event listener or queued job; auth is JWT with per-topic claims, so we map topics to users/tenants and reuse our identity model; MIT and protocol-standardized, so hub choice is swappable later.
  • What changed in this release (read before upgrading):
    • Default protocol is now 1.0 across Hub, FrankenPhpHub, MockHub and Jwt\LcobucciFactory.
    • Default cookie name is now __Secure-mercure_access_token — anything reading the old cookie breaks silently.
    • The Twig mercure() helper's query parameter is now match (was topic-style) — update templates and any client URLs built server-side.
    • LcobucciFactory claims are now authorization_details and require iss, aud, sub, client_id. This is the highest-risk change: our token issuance and topic-authorization tests all need rewriting.
    • FrankenPhpHub::publish() now throws a descriptive RuntimeException when mercure_publish() isn't available (e.g. under CLI) — better DX, and also a reminder that the FrankenPHP hub path only works under a FrankenPHP-served context. Guard queue workers accordingly.
    • WebTokenFactory gains a fully-specified Ed25519 algorithm (requires web-token/jwt-library 4.3, which deprecates polymorphic EdDSA). Use Ed25519 in the rotation runbook.
    • Minor: Debug\TraceableHub::getProvider() exception message fix.
  • What it isn't: a queue, a message store, or a WebSocket replacement. No presence, no client-to-server streaming, no delivery guarantees beyond reconnect + Last-Event-ID.
  • What we own: the service provider/config, protocol-version pinning, topic naming convention, token issuance (including iss/aud/sub/client_id) and key rotation, the hub deployment and its monitoring, and the frontend fallback-to-polling path. There is no Laravel bundle to lean on — this is Symfony code we wire ourselves.
  • Maturity caveat: pre-1.0 (v0.9.x), small downstream footprint, actively maintained and visibly converging on 1.0. Fine for a scoped pilot with pinned versions; the 0.9.0 breaking changes are the concrete cost of pre-1.0 and should be estimated before we put this on a launch critical path.
  • Success metrics for the pilot: publish→client p95 latency, reconnect/fallback rate, hub availability, updates per active session, infra cost per 1M updates, engineering hours to first feature vs. the Reverb/Pusher estimate, and — new — hours spent on the 0.9.0 migration itself, as a proxy for future upgrade drag.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager