nowo-tech/hot-reload-bundle

Symfony bundle that injects FrankenPHP (Dunglas) Hot Reload client assets when FRANKENPHP_HOT_RELOAD is available.

Maintainers

Package info

github.com/nowo-tech/HotReloadBundle

Documentation

Type:symfony-bundle

pkg:composer/nowo-tech/hot-reload-bundle

Transparency log

Statistics

Installs: 99

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.4.1 2026-08-19 16:29 UTC

This package is auto-updated.

Last update: 2026-08-19 16:29:20 UTC


README

CI Packagist Version Packagist Downloads License PHP Symfony GitHub stars Coverage

Found this useful? Install from Packagist · Give it a star on GitHub so more developers can find it.

Hot Reload Bundle — Symfony integration for FrankenPHP Hot Reload (dunglas/frankenphp-hot-reload). When enabled, it injects the Mercure hub meta tag, optional Idiomorph, and the frankenphp-hot-reload ESM module into HTML responses so the browser can morph or reload after PHP (and watched) file changes. Dev-only · PHP 8.1+ · Symfony 7.4+ and 8.0–8.2.

📋 Compatible with Symfony 7.4+ and 8.0–8.2 — PHP 8.1+ (Symfony 8.x requires PHP 8.4+).

FrankenPHP Friendly Worker Mode

This bundle is FrankenPHP worker mode friendly.

Pair with worker { …; watch } in your Caddyfile.

Features

  • Auto-injectHotReloadResponseSubscriber inserts assets before </head> (else </body>) on HTML responses.
  • Twig helper{{ nowo_hot_reload_assets() }} for manual layouts when auto_inject is off.
  • Env-aware — Renders only when enabled and (mercure_url or FRANKENPHP_HOT_RELOAD is set, or require_frankenphp_env: false).
  • Doctor commandphp bin/console nowo:hot-reload:check lists what is configured vs missing (Caddy mercure / hot_reload, env gate, auto-inject). The same checklist is on the profiler panel.
  • Idiomorph — Optional DOM morphing instead of a full page reload (on by default).
  • Web Debug Toolbar — Profiler panel (nowo_hot_reload) with status, truncated Mercure URL (full value on hover), environment checks, and CSP/preserve settings.
  • Preserve selectors — Marks Symfony Web Debug Toolbar ([id^="sfwdt"], .sf-toolbar, .sf-minitoolbar) with data-frankenphp-hot-reload-preserve (optional MutationObserver).
  • CSP-aware — Optional request-attribute nonce on the preserve boot script; can augment existing Content-Security-Policy script-src for jsDelivr (see docs/CSP.md).

Installation

composer require nowo-tech/hot-reload-bundle --dev

With Symfony Flex, the recipe registers the bundle and adds config. Without Flex, see docs/INSTALLATION.md.

Manual registration in config/bundles.php (prefer dev / test only):

return [
  // ...
  Nowo\HotReloadBundle\NowoHotReloadBundle::class => ['dev' => true, 'test' => true],
];

Server side: enable Mercure (anonymous) and php_server { hot_reload } in your Caddyfile. For worker mode, add worker { file …; watch }. Full environment guide: Configure the environment.

Environment setup

Hot Reload needs FrankenPHP + Caddy, not only Symfony YAML. FRANKENPHP_HOT_RELOAD is injected by FrankenPHP on HTTP requests — do not put it in .env.

  1. Register the bundle for dev / test only.
  2. Keep nowo_hot_reload.enabled: true and auto_inject: true (or call {{ nowo_hot_reload_assets() }}).
  3. Caddyfile: order mercure after encode, mercure { anonymous }, php_server { hot_reload } (worker: also worker { …; watch }).
  4. Recreate the FrankenPHP process/container after Caddy or Compose env changes.
  5. Validate:
php bin/console nowo:hot-reload:check
php bin/console nowo:hot-reload:check --caddyfile=path/to/Caddyfile

Then load an HTML page and open the Web Debug Toolbar Hot Reload panel (same checklist). Step-by-step Caddyfile, Docker notes, and troubleshooting: docs/ENVIRONMENT.md.

Requirements

  • PHP >=8.1 (<8.6); Symfony 8.x requires PHP 8.4+
  • Symfony 7.4+ and 8.0–8.2 (symfony/* ^7.4 || ^8.0)
  • FrankenPHP with Hot Reload + Mercure configured in the Caddyfile (dev)
  • twig/extra-bundle + twig/string-extra (REQ-TWIG-004) — required for {{ nowo_hot_reload_assets() }} and the profiler panel; enable TwigExtraBundle in the host app

Configuration

nowo_hot_reload:
  enabled: true
  auto_inject: true
  require_frankenphp_env: true
  allow_production: false
  # mercure_url: null  # defaults to $_SERVER['FRANKENPHP_HOT_RELOAD']
  idiomorph: true
  # idiomorph_script_url: 'https://cdn.jsdelivr.net/npm/idiomorph@0.7.4'
  # hot_reload_script_url: 'https://cdn.jsdelivr.net/npm/frankenphp-hot-reload@1.0.1/+esm'
  preserve_selectors:
    - '[id^="sfwdt"]'
    - '.sf-toolbar'
    - '.sf-minitoolbar'
  # csp_nonce_request_attribute: '_csp_nonce'
  csp_augment_script_src: true

Usage

With auto_inject: true (default), no template changes are needed when FrankenPHP sets FRANKENPHP_HOT_RELOAD (or you set mercure_url).

Manual Twig injection:

{{ nowo_hot_reload_assets() }}

Official references:

Demo

  • demo/symfony8 — Symfony 8.2 (PHP 8.5), host port 8011 by default (PORT in .env)

The demo runs FrankenPHP + Caddy in Docker. See docs/DEMO-FRANKENPHP.md.

Global demo commands: make -C demo help (e.g. make -C demo up-symfony8).

Development

make up
make install
make test
make cs-check
make phpstan
make release-check

Documentation

Additional documentation

Tests and coverage

  • Tests: PHPUnit (PHP)
  • PHP: 100%

License and author

MIT · Nowo.tech · Héctor Franco Aceituno