View .md

Realtime (Mercure)

How FeatherPanel pushes live updates through the Mercure hub in FrankenPHP: turning it on or off, the JWT keys, private topics, proxies and the polling fallback.

On this page

FeatherPanel uses the Mercure hub built into FrankenPHP to tell browsers that something changed, so pages refresh at once instead of polling. Events only say what changed, never the data itself; the browser fetches the new data through the normal API.

What uses it

TopicEvents
/servers/<uuidShort>Server state and backup changes.
/notificationsAnnouncements created, edited or deleted by an admin.
/users/<uuid>New items in the user’s notification inbox.
/admin/webspacesWebSpace changes in the admin list.

How it is turned on

On start, the backend sources caddy/frankenphp-env.sh, which reads FEATHERPANEL_MERCURE:

  • auto (default): uses MERCURE_SUBSCRIBER_JWT_KEY and MERCURE_PUBLISHER_JWT_KEY from the environment, else from storage/config/.env, else generates both once and saves them to .env. If both are at least 32 characters, the hub is mounted.
  • off: no hub, the panel polls.

The startup log prints FrankenPHP: live updates (Mercure) on or off.

How browsers connect

  1. The frontend calls POST /api/user/realtime/token with the topics it wants. The backend only grants topics the user may see and signs a token valid for one hour.
  2. The browser opens one stream per tab to /api/mercure and sends the token in the Authorization header, never in the URL.
  3. After a reconnect the page refetches, because the hub stores nothing (transport local).

Reverse proxies

The stream goes through /api/mercure, so any proxy that already forwards /api/* works. It must not buffer or compress the response. The hub sends X-Accel-Buffering: no for nginx and a heartbeat every 25 seconds to keep idle connections open. See Web server.

MERCURE_PUBLIC_URL overrides the URL the browser uses and MERCURE_PUBLISH_URL lets the backend publish to an external hub over HTTP. Neither is needed with the bundled setup.

Frequently asked questions

Do I have to set up Mercure?

No. The backend container generates the two keys on first start and turns the hub on by itself. Set FEATHERPANEL_MERCURE=off to disable it.

What happens when live updates do not work?

The panel falls back to polling, so pages still refresh, just less quickly. Check that your proxy does not buffer /api/mercure.

Can someone read other users' events?

No. Topics are private and the subscriber token only lists topics the signed-in user may see.