⭐ 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.2+ · Symfony 7.4+ and 8.0–8.2.
📋 Compatible with Symfony 7.4+ and 8.0–8.2 — PHP 8.2+ (Symfony 8.x requires PHP 8.4+).
This bundle is FrankenPHP worker mode friendly.
Pair with worker { …; watch } in your Caddyfile.
- Auto-inject —
HotReloadResponseSubscriberinserts assets before</head>(else</body>) on HTML responses. - Twig helper —
{{ nowo_hot_reload_assets() }}for manual layouts whenauto_injectis off. - Env-aware — Renders only when
enabledand (mercure_urlorFRANKENPHP_HOT_RELOADis set, orrequire_frankenphp_env: false). - Doctor command —
php bin/console nowo:hot-reload:checklists what is configured vs missing (Caddymercure/hot_reload, env gate, auto-inject,client_mode). The same checklist is on the profiler panel. - Multi-tab client modes —
client_mode:cdn(default),visibility,shared_worker, oralwaysfor HTTP/1.1-friendly Mercure strategies (see docs/USAGE.md). - Idiomorph — Optional DOM morphing instead of a full page reload (on by default).
- Web Debug Toolbar — Profiler panel (
nowo_hot_reload) with tabs: Environment checks, Runtime, Client assets, CSP, Help; truncated Mercure URL in the toolbar (full value on hover). - Preserve selectors — Marks Symfony Web Debug Toolbar (
[id^="sfwdt"],.sf-toolbar,.sf-minitoolbar) withdata-frankenphp-hot-reload-preserve(optionalMutationObserver). - CSP-aware — Optional request-attribute nonce on the preserve boot script; can augment existing
Content-Security-Policyscript-srcfor jsDelivr (see docs/CSP.md).
composer require nowo-tech/hot-reload-bundle --devWith 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.
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.
- Register the bundle for
dev/testonly. - Keep
nowo_hot_reload.enabled: trueandauto_inject: true(or call{{ nowo_hot_reload_assets() }}). - Caddyfile:
order mercure after encode,mercure { anonymous },php_server { hot_reload }(worker: alsoworker { …; watch }). - Recreate the FrankenPHP process/container after Caddy or Compose env changes.
- Validate:
php bin/console nowo:hot-reload:check
php bin/console nowo:hot-reload:check --caddyfile=path/to/CaddyfileThen 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.
- 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; enableTwigExtraBundlein the host app
nowo_hot_reload:
enabled: true
auto_inject: true
require_frankenphp_env: true
allow_production: false
# mercure_url: null # defaults to $_SERVER['FRANKENPHP_HOT_RELOAD']
# client_mode: shared_worker # cdn|visibility|shared_worker|always
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: trueWith 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/symfony8— Symfony 8.2 (PHP 8.5), host port 8011 by default (PORTin.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).
make up
make install
make test
make cs-check
make phpstan
make release-check- Installation
- Environment setup (Caddy / FrankenPHP)
- Configuration
- PSR evaluation (REQ-CS-007)
- CSP
- Usage
- Contributing
- Code of Conduct
- Changelog
- Upgrading
- Release
- Security
- Engram
- Spec-driven development
- GitHub Spec Kit
- Tests: PHPUnit (PHP)
- PHP line coverage: maintained via
make test-coverage/make release-check(see CI)
MIT · Nowo.tech · Héctor Franco Aceituno
