feat(home): live updates via Mercure — server pushes device state to the PWA
CI / test (push) Has been cancelled
CI / test (push) Has been cancelled
Subscribe per-device with a Symfony Mercure hub: server publishes a fresh device payload after every poll (200/304/204), every PATCH, and every lock/unlock. The frontend opens one EventSource per device topic and splats inbound JSON straight into the devices store — same shape as GET /api/devices, so no envelope handling. Topic: https://pictureframe.edholm.me/devices/{id} Stack mirrors aqua-iq: - symfony/mercure-bundle + config/packages/mercure.yaml - App\Service\MercurePublisher (errors swallowed + logged; a flaky hub must not break a poll response) - App\Service\DeviceSerializer extracted as the single source of truth for the wire shape (REST + Mercure share it) - Frontend useDeviceMercure() composable: opens/closes EventSources to match the device list reactively, reconnects on hub-side closes - SpaController exposes MERCURE_PUBLIC_URL via window.__PF_MERCURE_URL__ Production compose adds a dunglas/mercure container with Traefik labels for pictureframe.edholm.me/.well-known/mercure (handled separately on the host since the file isn't in this repo). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -52,3 +52,12 @@ MAILER_SENDER=noreply@pictureframe.edholm.me
|
||||
SHARE_TOKEN_TTL_DAYS=7
|
||||
HARD_DELETE_TOKEN_TTL_DAYS=30
|
||||
###< pictureframe ###
|
||||
|
||||
###> symfony/mercure-bundle ###
|
||||
# Internal URL the Symfony app uses to publish — matches the mercure service name.
|
||||
MERCURE_URL=http://mercure/.well-known/mercure
|
||||
# Public URL the browser subscribes to. Overridden in production envs.
|
||||
MERCURE_PUBLIC_URL=http://localhost/.well-known/mercure
|
||||
# Default secret for dev only; production sets a 32-byte hex value via .env.prod.
|
||||
MERCURE_JWT_SECRET=changeme
|
||||
###< symfony/mercure-bundle ###
|
||||
|
||||
Reference in New Issue
Block a user