nowo-tech / pwa-bundle
Symfony bundle to turn any application into a fully configurable Progressive Web App (manifest, service worker, offline, install prompt)
Fund package maintenance!
Requires
- php: >=8.2 <8.6
- nowo-tech/ui-kit-bundle: ^2.2
- symfony/config: ^7.4 || ^8.0
- symfony/dependency-injection: ^7.4 || ^8.0
- symfony/deprecation-contracts: ^2.5 || ^3.0
- symfony/framework-bundle: ^7.4 || ^8.0
- symfony/http-kernel: ^7.4 || ^8.0
- symfony/routing: ^7.4 || ^8.0
- symfony/twig-bundle: ^7.4 || ^8.0
- symfony/yaml: ^7.4 || ^8.0
- twig/extra-bundle: ^3.12
- twig/string-extra: ^3.12
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- igor-php/igor-php: ^0.10.0
- minishlink/web-push: ^11.0
- nowo-tech/brand-contracts: ^1.0
- nowo-tech/phpstan-frankenphp: ^1.0
- nyholm/psr7: ^1.8
- phpstan/extension-installer: ^1.0
- phpstan/phpstan: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: ^10.0
- rector/rector: ^2.0
- symfony/browser-kit: ^7.4 || ^8.0
- symfony/dom-crawler: ^7.4 || ^8.0
- symfony/http-client: ^7.4 || ^8.0
- symfony/security-core: ^7.4 || ^8.0
- symfony/security-csrf: ^7.4 || ^8.0
- symfony/translation: ^7.4 || ^8.0
- vincentlanglet/twig-cs-fixer: ^4.0
Suggests
- minishlink/web-push: ^11.0 — required by nowo_pwa.web_push (server-side Web Push sender + push diagnostics test endpoint)
- nowo-tech/brand-contracts: ^1.0 — brand name, colours and icons for the manifest and head tags from a BrandProviderInterface service (nowo_pwa.brand, spec 220)
- nyholm/psr7: PSR-7/PSR-17 implementation needed by minishlink/web-push to build push requests (checked at container compile time when nowo_pwa.web_push.enabled)
- symfony/http-client: Recommended PSR-18 client for minishlink/web-push: receives the bundle deadlines web_push.timeout / connect_timeout (other PSR-18 clients keep their own timeouts)
- symfony/security-bundle: Required by nowo_pwa.web_push.test_notification (authenticated endpoint)
- symfony/security-csrf: Required by nowo_pwa.web_push.test_notification (CSRF-protected endpoint)
Provides
None
Conflicts
- nowo-tech/brand-contracts: <1.0 || >=2.0
Replaces
None
- dev-main
- v1.15.0
- v1.14.1
- v1.14.0
- v1.13.0
- v1.12.0
- v1.11.0
- v1.10.2
- v1.10.1
- v1.10.0
- v1.9.1
- v1.9.0
- v1.8.0
- v1.7.1
- v1.7.0
- v1.6.1
- v1.6.0
- v1.5.3
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.0
- v1.3.3
- v1.3.2
- v1.3.1
- v1.3.0
- v1.2.1
- v1.2.0
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.1
- v1.0.0
- dev-feat/brand-s4
- dev-feat/motion-tokens
- dev-feat/install-prompt-host-paint-push-entry
- dev-chore/symfony-security-2026-11-04
This package is auto-updated.
Last update: 2026-11-09 23:35:33 UTC
README
⭐ Found this useful? Give it a star on GitHub so more developers can find it.
Turn any Symfony application into a Progressive Web App with a fully configurable manifest, service worker, offline page, and install prompt — no vendor lock-in, no hardcoded assets.
This bundle is FrankenPHP worker mode friendly.
This includes running when the kernel is not rebooted between requests (reset_kernel false); see FrankenPHP worker audit. The only runtime blocking I/O, optional Web Push deliveries, is bounded by web_push.connect_timeout / timeout so a slow push service cannot pin a worker thread (HTTP timeouts).
Install prompt — host UiKit theme, brand mark from a one-block override |
Offline fallback — self-contained status page cached by the service worker |
Features
- Web App Manifest generated from
nowo_pwa.yaml(name, icons, shortcuts, theme, display mode, scope, start URL) - Manifest overlay — implement
ManifestOverlayProviderInterface(tagnowo_pwa.manifest_overlay_provider, autoconfigured) to overlay brand/colors onto the manifest - Brand provider (optional) — with
nowo-tech/brand-contractsand aBrandProviderInterfaceservice (e.g. InstanceSettingsBundle's brand bridge), the manifest and head tags follow the brand name, colours and app icon; the config stays the fallback (nowo_pwa.brand, see USAGE) - Service worker with configurable cache strategy (
network-first,cache-first,stale-while-revalidate), precache URLs, and offline fallback - Twig helpers
nowo_pwa_head(),nowo_pwa_install_prompt(),nowo_pwa_install_links(), andnowo_pwa_enabled()with route targeting (all/only/except, route names or URL paths) - Web Profiler panel
nowo_pwa(manifest/SW status in debug) - Install prompt modes —
banner,flash(inline), ormodal; dismiss remind / never-ask-again options - UiKit page contract (REQ-UI-003,
nowo-tech/ui-kit-bundle^2.2) — widgets on UiKit theme slots and tokens, offline page on the self-contained UiKit status layout (templates) - Override-friendly Twig templates with install/offline blocks (
@!NowoPwaBundleone-block overrides), bundledpwa.csstokens, and translations (en, es, fr, it, pt, de, nl; REQ-TWIG-001 / REQ-I18N-001) - TypeScript client for SW registration and install banner (Vite build →
pwa.js) - Web Push (optional) —
WebPushSenderInterface(minishlink/web-push 11, VAPID, anti-SSRF endpoint guard), dependency checks at compile time, and an opt-in CSRF-protected test notification endpoint (nowo_pwa_push_test) - Push diagnostics —
push-checks.ts+ Stimulus peerpush-diagnostics+ partialpwa/push_diagnostics.html.twig(per-step checklist: support, VAPID, permission, service worker, subscription/key match, server copy) - Browser hints — Stimulus peer
browser-hint+ partialspwa/browser_hint.html.twig/pwa/browser_guide.html.twig(per-browser install + push help) - Works with Symfony 7.4+ and 8.x; no database required
Installation
composer require nowo-tech/pwa-bundle
# config/packages/nowo_pwa.yaml nowo_pwa: manifest: name: 'My Application' short_name: MyApp theme_color: '#0f172a' icons: - { src: '/icons/icon-192.png', sizes: '192x192', type: image/png } - { src: '/icons/icon-512.png', sizes: '512x512', type: image/png } service_worker: precache_urls: ['/', '/offline'] offline_url: '/offline'
In your base layout:
<head> {{ nowo_pwa_head() }} </head> <body> {% block body %}{% endblock %} {{ nowo_pwa_install_prompt() }} {{ nowo_pwa_install_links() }} </body>
See Installation and Configuration.
Documentation
- Installation
- Configuration
- Usage
- Contributing
- Code of Conduct
- Changelog
- Upgrading
- Release
- Security
- Engram
- Spec-driven development
- GitHub Spec Kit
Additional documentation
- GitHub Actions CI requirements
- PSR evaluation (REQ-CS-007)
- Templates (UiKit page contract)
- Demo with FrankenPHP
- FrankenPHP worker audit
Tests and coverage
- PHP: 100% (
composer test-coverage-100enforces--min-percent=100) - TS/JS: 100% (Vitest thresholds in
vitest.config.ts)
make test make test-ts make test-coverage make release-check # includes demo healthcheck on port 8025
Playwright end-to-end tests and the README screenshots (WebP under docs/images/demo/): make -C demo/symfony8 test-e2e
and make -C demo/symfony8 demo-screenshots (REQ-DEMO-013).
License
MIT — see LICENSE.


