nowo-tech/pwa-bundle
A Symfony bundle for adding Progressive Web App capabilities to your site, with configuration for web app manifests, service workers, caching, and installability so users get a fast, app-like experience.
Framing note (read first): the package is a Symfony bundle, not a Laravel package. Nothing in v1.11.0 changes that. The description's claim that it "turns any application into a PWA" remains marketing framing, not a technical property — a Symfony bundle only executes inside a Symfony kernel. Any Laravel assessment is therefore an assessment of whether to port the concept, not whether to install the dependency.
What changed in v1.11.0: one addition — nowo_pwa.install_prompt.mark_template, a Twig configuration key that lets a host supply an inline brand mark (e.g. an inline SVG) for the install prompt without overriding pwa/install_prompt.html.twig wholesale, and which takes precedence over the existing mark_asset option. No breaking changes, no deprecations, no dependency changes, no new framework support. It is a narrow ergonomics improvement for hosts that were already forking the bundle's template.
Architecture fit — poor as a direct dependency, moderate as a reference implementation. Unchanged.
A Symfony bundle contributes value through mechanisms Laravel does not have: a Bundle class registered in config/bundles.php, a DependencyInjection\Extension that compiles a configuration tree, compiler passes, and tagged services resolved by the Symfony container. Installing this via Composer into a Laravel app succeeds at the filesystem level and does nothing at runtime. Laravel ships several Symfony components (HttpFoundation, Console, Routing, Finder, Mime, ErrorHandler), but not the HttpKernel + full DI stack the bundle lifecycle depends on.
What v1.11.0 tells us technically (the useful part). The new option is a Twig template path, consumed by a Twig-rendered install-prompt partial. That is a concrete confirmation of a suspicion raised in the prior assessment: the bundle's presentation layer is Twig-coupled, not framework-neutral markup. For a port this is clarifying rather than blocking — the idea (a brandable, theme-following inline SVG mark injected into the install prompt without template forking) is directly portable to a Blade partial plus a config key, and arguably cleaner in Blade because Laravel's component/slot model expresses "default mark, overridable mark" natively. The implementation is not portable at all.
What is actually reusable: unchanged. The domain content — a manifest JSON document; a service worker served from the scope root with Service-Worker-Allowed and correct cache headers; a client-side beforeinstallprompt handler. v1.11.0 adds one small item to the portable list: the install-prompt branding config surface (mark source, precedence order, theme-following inline SVG) is now explicit enough to copy as a design decision rather than infer.
Integration feasibility. Direct install: not viable, cost near zero, value zero, leaves dead code and a false signal in composer.json. Bridge: technically possible, categorically not worth it for a manifest generator and a static JS file — reject. Port: the realistic path. Scope is unchanged by this release: service provider, publishable config, manifest route, service worker route, Blade/asset publish. Still a small, well-understood build — 3–7 engineering days for manifest + SW + headers + offline fallback, plus roughly 0.5 day for install-prompt branding now that the shape is known.
Technical risk — high relative to delivered value; marginally improved but not re-rated.
v1.10.2 → v1.11.0 sequence plus an automated release-check gate pinning a commit SHA indicates a real (if small) release process with automated verification. That is better than "no release history at all" and I am softening that specific prior finding. The last-release date of 2026-10-13 remains unverifiable against a normal cadence — treat the supply-chain metadata as unconfirmed and inspect the repository directly.Key questions — updated:
release-check gate cover a test suite, or only packaging integrity?Stack fit. Target Laravel 10/11/12 on PHP 8.1+. Header manipulation (Service-Worker-Allowed, Cache-Control, Content-Type: application/manifest+json) maps cleanly onto middleware and route responses. Feature set is frontend-framework agnostic, so Blade, Inertia, Livewire, or a separate SPA all work — v1.11.0 reinforces this: the branding hook is a slot, which maps to a Blade component or a @include with a default far more idiomatically than to Twig template inheritance. Vite remains the integration hazard: the service worker must be served from the scope root (/sw.js), not /build/assets/sw-abc123.js, and must not be fingerprinted.
Migration path. Do not adopt the bundle. Vendor the schema, the service worker template, and now the install-prompt branding contract as design input, then implement natively.
Configuration.php, SW template, and the install-prompt Twig partial. Extract the config surface, the cache-versioning approach, and the mark-precedence rules (mark_template over mark_asset, with a fallback). Decide build-vs-borrow per element.application/manifest+json, driven by config/pwa.php. Icon set, start_url, display, theme_color, scope. Publishable via php artisan vendor:publish.beforeinstallprompt / appinstalled.Compatibility considerations. The bundle's own version constraints matter only insofar as they indicate how recently the problem space was considered — they do not constrain your build. The real constraints are browser support matrix (Safari's service worker and install behavior still diverges from Chromium), CSP configuration (worker-src, plus inline SVG in the prompt — inline SVG is CSP-safe, but a host using mark_asset needs img-src allowances), and existing CDN rules that would serve a stale sw.js.
Sequencing rationale. Unchanged. Manifest first — low-risk, independently shippable, delivers most visible benefit. Service worker second, behind a feature flag, because it is the only component that can degrade a healthy site. Offline and install-prompt polish last, after the caching model has been validated in production. v1.11.0 is entirely a Phase 4 concern and does not alter the ordering.
Maintenance. You own it. Upstream provides no upgrade path, and v1.11.0 is a good illustration of why that matters little: a change to install-prompt branding is not something you would ever want to schedule a merge window for. Budget a recurring line item for service worker version bumps on every deploy that changes cached assets, plus periodic review of caching strategy. Assign a named owner; an unowned service worker is an incident waiting for a quiet quarter.
Support. No community, no dependents, no issue history to mine. The release-check automation suggests the maintainer at least packages carefully — a mild positive for reading the code, not a substitute for internal expertise. Keep the ported surface small and boring; a manifest route and a conservative service worker are supportable by any senior Laravel developer, an elaborate multi-strategy caching engine is not.
Scaling. Manifest and SW are static per deployment and belong at the CDN edge, short TTL on sw.js, long TTL on icons. Multi-tenant deployments need a per-tenant manifest (name, colors, start_url) — the bundle's config-tree model does not naturally express this, and v1.11.0's single global mark_template key confirms the config surface is deployment-scoped, not tenant-scoped. Design the config as tenant-overridable from the start rather than retrofitting, and watch for cache-key collisions if tenants share a CDN distribution.
Failure modes to design against, explicitly:
skipWaiting + clients.claim policy up front.mark_template/mark_asset path yields a blank or 404ing icon in the prompt. Add a render-time fallback and a smoke test.Ramp-up. Low for Phase 1 (half a day of reading). Moderate for the service worker layer — 1–2 weeks before a developer is genuinely confident debugging lifecycle issues in DevTools' Application panel and reading Lighthouse PWA audits correctly. Phase 4 branding work is trivial by comparison and can be handed to a mid-level developer. Frontend/QA must be trained to test offline behavior and install flows; these paths are invisible to happy-path QA and will otherwise ship untested.
Bottom line for a TPM: treat this repository as a specification, not a dependency. v1.11.0 is a minor, non-breaking, install-prompt-only feature — it neither weakens nor materially strengthens the case, and it explicitly does not touch the one genuinely risky subsystem (the service worker). The decision is unchanged: the 0-star/0-dependent profile, unverifiable release metadata, and single-maintainer risk make adoption unattractive, while the Symfony-to-Laravel impedance mismatch makes it technically inapplicable as-is. The capability is genuinely worth having, and the port is small enough to own outright. Recommendation: fund a one-sprint native build, cite v1.11.0 as design input for the install-prompt branding config specifically, and do not add it to composer.json.
How can I help you explore Laravel packages today?