jeffersongoncalves/laravel-clarity
Laravel Clarity is a lightweight package that brings Microsoft Clarity analytics to your Laravel app. Publish the config, add the tracking snippet, and start capturing session recordings, heatmaps, and click data with almost no setup.
Architecture fit. The change is additive and narrow: every <script> tag the package emits now carries the application's Vite CSP nonce when one is set. Architecturally this is the right shape for a Laravel package — it consumes a first-party platform primitive (Vite::useCspNonce() / Vite::cspNonce()) rather than introducing its own nonce configuration, storage, or generation. That means one source of truth for the nonce across the app, no competing config surface, and no new coupling to a specific CSP package (laravel-security-headers is cited as an example, not a dependency).
Integration feasibility. Low effort. In a standard Laravel app already using Vite with a nonce — typically set in middleware and consumed by @vite / @routes — the package should "just work" with zero config changes. The main feasibility question is where the nonce is resolved. If it's read at render time from the container/Vite instance, it composes correctly with Blade and with any response-time middleware. If it's resolved at boot, at config-publish time, or inside a cached/compiled artifact, the nonce will be stale and worthless.
Technical risk. Moderate, concentrated in three areas:
script-src enforcement. This is the single highest-risk scenario and needs an explicit answer.<script> rendered by the package" is the claim. That needs to be true for inline bootstrap snippets, external CDN/vendor tags, and any script injected client-side at runtime (a JS-injected tag cannot inherit a server nonce and needs 'strict-dynamic' or a hash).No breaking-change signal: when no nonce is set, behavior is unchanged, which is consistent with a minor version bump.
Key questions.
Vite::cspNonce() directly, and does it also honor a nonce set by laravel-security-headers when Vite's nonce was not used?'strict-dynamic', or support for hash-based policies as an alternative to nonces?Stack fit. Fits any Laravel 10/11+ application using Vite, which is the default for new projects and the majority of maintained ones. It also fits apps that enforce CSP via laravel-security-headers or hand-rolled middleware, since the package reads the nonce rather than owning it. Apps not using CSP see no behavioral change.
Migration path. Effectively a no-op upgrade. Bump the constraint, run the suite, confirm rendered markup is byte-identical when no nonce is configured. The only planned work is on the host side: confirming which middleware sets the nonce and that it runs early enough in the stack.
Compatibility. Watch two things. First, nonce sourcing: apps that set a nonce outside Vite's API (custom middleware setting a header and a container binding) may not be picked up — verify whether the package reads the Vite API only or also a generic binding. Second, apps with response caching (CDN edge caching, spatie/laravel-responsecache, full-page caches) must exclude nonce-bearing responses or disable the nonce for cached routes; this is a host-app configuration requirement the package should document.
Sequencing.
Content-Security-Policy-Report-Only.<script> output for the nonce attribute; confirm it matches the response header on the same request.Content-Security-Policy) in staging, then production, keeping Report-Only collection for a burn-in window.'unsafe-inline' from script-src — that removal is the actual security win, and it is a separate, reversible step from the package upgrade.Maintenance. Near zero. No new configuration, no new dependency, no schema or migration. The maintenance obligation shifts to documentation: the package should state which nonce API it reads and what middleware ordering it assumes, otherwise support load will show up as "CSP blocks the package's script" tickets that are actually host misconfigurations.
Support. Expect an initial spike in CSP-related reports during rollout, most of them non-package issues (middleware order, caching, a second CSP header from a proxy or CDN overriding the app's policy). Arm support with a triage script: check for the nonce attribute in the page source, compare it to the header, check for a second CSP header, check whether the response was served from cache. Failure is quiet by design — a blocked script produces a console error and a report-uri hit, not an application exception — so it will not surface in error tracking unless browser console/report collection exists.
Scaling. Negligible performance impact: one attribute per tag, one container/Vite lookup per render. The scaling concern is distributed-response caching, not compute — nonces and shared caches are fundamentally at odds, and any horizontally scaled deployment behind a CDN needs the cache-bypass or cache-exclusion policy settled before enforcement. Multi-tenant setups should be spot-checked, since nonce-per-request must not be shared across tenants.
Failure modes.
'unsafe-inline', the security benefit is negated and the upgrade was pointless. Governance, not code.Ramp-up. Trivial for engineers — the change is invisible unless CSP is in play. The real ramp-up is organizational: getting the team fluent in nonce lifecycle, middleware ordering, and cache interaction. Budget a short working session with whoever owns security headers, and treat the 'unsafe-inline' removal as a tracked milestone rather than a side effect of the version bump. Net assessment: this release materially improves enterprise/strict-CSP adoptability at almost no integration cost; approve, with caching and middleware ordering verified before enforcement.
How can I help you explore Laravel packages today?