Skip to content
LaravelBlog

laravel/framework: Add support for installing Mercure via broadcasting install command

LaravelBlogBot
LaravelBlogBot , 4 mins read

Contributed by Lea-Bar

Laravel 13.x recently gained native Mercure broadcasting support (via PR #61474), but the scaffolding command php artisan install:broadcasting didn't yet know how to set it up. PR #61587 closes that gap: the installer now offers Mercure as a first-class driver, installs the required Composer packages, walks you through hub configuration, and writes a ready-to-use Echo setup. If you're upgrading from v12.70.0 and want to try Mercure, this makes onboarding a single command instead of a manual checklist.

A new --mercure option for the broadcasting installer

The command signature gains a dedicated flag, mirroring the existing --reverb, --pusher, and --ably options:

php artisan install:broadcasting --mercure

If you run the command without flags, the interactive driver prompt now lists Mercure alongside Reverb, Pusher, and Ably. Internally, resolveDriver() was refactored from a series of if checks into a single match (true) expression — behavior is identical, just cleaner, with 'mercure' => 'mercure' added to both the option checks and the selection list.

Multi-package Composer installs

Previously, installDriverPackages() hard-coded a single package per driver through a match statement. That doesn't work for Mercure, which needs two packages. The method was rewritten around a new $driverPackages property that maps each driver to an array of package/constraint pairs:

protected $driverPackages = [
    'pusher' => ['pusher/pusher-php-server' => '*'],
    'ably' => ['ably/ably-php' => '*'],
    'mercure' => ['symfony/mercure' => '^0.8', 'web-token/jwt-library' => '^4.1'],
];

Choosing Mercure means Composer requires symfony/mercure at ^0.8 and web-token/jwt-library at ^4.1. The rewrite also improves behavior for everyone: packages already installed are filtered out before any Composer call is made, and constraints other than * are appended to the package name, so the installer can pin specific versions where needed.

Guided Mercure configuration in .env

Choosing Mercure triggers a new collectMercureConfig() flow. You're first asked which hub you'll use — FrankenPHP's built-in hub or a standalone Mercure hub.

For a standalone hub, the installer prompts for the publishing URL and the public URL browsers subscribe to (defaulting the public URL to the hub URL), then writes:

MERCURE_URL=https://example.com/.well-known/mercure
MERCURE_PUBLIC_URL=https://example.com/.well-known/mercure
VITE_MERCURE_HUB_URL='${MERCURE_PUBLIC_URL}'

One nice touch: if the public URL uses plain http://, the installer sets MERCURE_COOKIE_NAME=mercure_access_token and emits a warning reminding you to configure cookie_name mercure_access_token on your hub — a common gotcha when cookies can't be marked Secure.

In all cases you're prompted for the Mercure JWT secret (validated to be at least 32 bytes, with a random hex secret generated if you leave it empty), and you can opt into end-to-end encrypted channels, which writes a MERCURE_ENCRYPTION_KEY as a base64-encoded 32-byte random value.

Echo wiring out of the box

The command also ships a new echo-js-mercure.stub, so your resources/js/echo.js gets a working client configuration instead of a Pusher-shaped one:

import Echo from 'laravel-echo';

window.Echo = new Echo({
    broadcaster: 'mercure',
    host: import.meta.env.VITE_MERCURE_HUB_URL,
});

Upgrade impact

For teams coming from v12.70.0, this is purely additive scaffolding:

  • No breaking changes. Pusher, Ably, and Reverb flows behave exactly as before; the $driverPackages refactor is a reorganization of the same logic.
  • New capability only. If you previously set up Mercure manually — composer require symfony/mercure web-token/jwt-library, hand-editing .env, and writing the Echo config yourself — the installer now automates all of it. There's no migration needed for existing setups.
  • One caveat: if you already have symfony/mercure or the JWT library installed at a version outside the ^0.8 / ^4.1 constraints, the installer will skip it because the package is detected as installed; verify your versions satisfy Mercure broadcasting's requirements.
  • Scripted installs: CI or docs that call install:broadcasting can now pass --mercure for non-interactive setup.

Takeaways

  • php artisan install:broadcasting --mercure now fully scaffolds Mercure broadcasting: packages, .env, and Echo config.
  • Mercure requires two Composer packages — symfony/mercure ^0.8 and web-token/jwt-library ^4.1 — both installed automatically.
  • The installer prompts for hub type, URLs, JWT secret, and optional encryption, with a helpful warning for HTTP-only hub URLs.
  • The package-installation rewrite benefits all drivers: multiple packages with version constraints and no redundant Composer runs.
  • No action required if you don't use Mercure; existing Reverb/Pusher/Ably workflows are unchanged.

Sources

Related Articles