shuvroroy/nova-dynamic-views
A Laravel Nova package for creating dynamic, configurable views in your admin panel. It lets you build reusable, data-driven Nova pages and tailor what users see without custom Vue components, with straightforward installation and integration into existing Nova resources.
Architecture fit. shuvroroy/nova-dynamic-views is a narrow, single-purpose Nova extension: it moves where Nova's header and toolbar slots resolve their Blade views from hard-coded PHP on resource classes into a configuration-driven registration path. Architecturally that is a good fit for Laravel Nova — it hooks the same slots every Nova app already customizes, auto-discovers through a service provider, and introduces no new runtime, queue, or storage dependency. It is a convenience layer over existing framework surface, not a new subsystem. That is both its appeal and the reason it is a weak candidate for anything strategic: the underlying capability already exists natively via Nova::header() and per-resource header()/toolbar() overrides, so we are buying de-duplication and centralization, not new capability.
Integration feasibility. High, with a caveat. Install is a single composer require, service-provider auto-discovery, and vendor:publish plus view:clear. The real integration cost is not installation but discovery: the README, release notes, and description are all thin, and v2.4.0's changelog is a one-line "Support Nova version 5.11.0" with no statement about backward compatibility. Our engineers will have to read src/ and the service provider directly to confirm the resolution order (global default → per-resource override → conditional override) before we can design against it. Budget one focused spike, not a sprint.
Technical risk. Ranked by likelihood × impact:
Key questions to resolve before approval:
composer.json constraint?Stack fit. Requires an existing Laravel + Laravel Nova application; it is not applicable to anything else, and it offers nothing to customer-facing surfaces. Best fit is an internal admin panel with recurring chrome variation across resources, tenants, brands, or roles: environment badges, tenant context, support links, global quick actions. Worst fit is a single one-off header change, where Nova::header(fn () => view(...)) in NovaServiceProvider is cheaper and carries zero dependency risk.
Migration path. Treat adoption as a contained refactor, not a platform migration:
"shuvroroy/nova-dynamic-views": "2.4.*". Install, publish, view:clear, verify auto-discovery. Confirm Nova version compatibility in composer.json first.src/ and the service provider. Document the actual resolution order and precedence in the ticket — that document becomes our durable asset, because upstream does not provide one.App\Nova\NovaChrome (or a DynamicChrome trait) exposing our own vocabulary — headerFor(string $resource), toolbarFor(string $resource). Every package call goes through it. If the package stalls, we rewrite one file. This is the cheapest insurance available and it is non-negotiable.User or Invoice — replace its toolbar with a branding bar plus two quick links. Then open a resource we did not touch and verify whether it changed. That second look answers the global-vs-scoped question empirically.NOVA_DYNAMIC_CHROME=false falling back to stock Nova chrome, so rollback is one line and zero redeploy of application code.Compatibility. Lock to Nova 5.11.0 for the pilot and confirm the constraint in composer.json rather than trusting the changelog. Every Nova minor bump becomes a manual staging pass over each dynamic view before production — Nova has changed view-resolution behavior before, and there is no vendor to catch it for us.
Sequencing. Adapter and allowlist config land before the first dynamic view, not after. Feature flag lands with the first view. Tests land with the first view. If the spike shows fewer than ~5 resources with divergent chrome, stop and take the native path — the dependency is not earning its keep. Do not parallelize rollout across many resources until one view has survived a full deploy cycle including view:clear.
Fallback plan. Keep Nova::header()/resource header() documented from day one as an actively supported alternative, not a footnote. Removal must be a refactor, never a rewrite.
Maintenance. Effectively zero upstream maintenance — one maintainer, no dependents, no issue volume, single-line changelogs. That means all maintenance is ours: pinning, diff review on every bump, and a manual regression pass on Nova upgrades. Small ongoing cost, but it is a permanent tax on a named engineer, and it must be staffed rather than assumed.
Support. No vendor, no SLA, no security advisory channel, no community validation to lean on when something breaks. Internal support model: adapter abstraction contains the blast radius to one file; rendered-output tests (actingAs($admin)->get('/nova/resources/users')->assertOk()->assertSee('Production')) are our de facto specification, since upstream provides none. One test per dynamic view is the minimum bar.
Scaling. Scales fine across resources — that is the point, and centralizing N near-identical overrides into one registration path is a genuine maintainability win. Two scaling constraints:
<x-nova.env-badge />, <x-nova.tenant-switcher />) so per-tenant and per-role variation does not become N nearly identical header files. Push role/permission/tenant branching into PHP where it is testable; keep Blade dumb.Also note what does not scale: custom JS/CSS. The package owns the view slot, not the asset pipeline. Vite/Mix builds or explicit Nova::script()/Nova::style() remain ours.
Failure modes and mitigations.
| Failure mode | Symptom | Mitigation |
|---|---|---|
| Precedence confusion | Header appears where it shouldn't; global beats resource-level | Temporary Log::debug() on resolved view name + matched condition; document resolution order after source read |
| Stale compiled view | Works locally, wrong on staging | php artisan view:clear in the deploy script next to config:cache |
| Nova minor bump | Resolution behavior changes silently | Pin, manual staging pass per Nova upgrade, one rendering test per view |
| Tenant cross-leak | Wrong tenant's chrome rendered, or path traversal | Config allowlist only; never string-concatenate user input into a view name |
| Header ≠ toolbar | Looks correct in one slot, broken in the other | Verify both at narrow widths before sign-off — different spacing and responsive behavior |
| Admin panel slowdown | Every Nova page slower after rollout | Ban queries and outbound calls in header partials; cache or hardcode |
| Upstream abandonment | No fixes, no security patches | Thin adapter + documented native fallback + named owner + quarterly "fork or drop" review |
Ramp-up. Low — a Laravel-fluent engineer reaches productive use in under a day, and the spike plus source read is roughly one engineer-day total. The binding constraint is not skill, it is ownership: someone must be named to hold the pin, run the Nova-upgrade regression pass, and make the fork-or-drop call. That is a half-day-per-quarter commitment, not an ongoing workload — but it is real, and unassigned it becomes the failure mode.
Recommendation. Approve as a time-boxed pilot in a non-critical admin area, gated on: (a) source review confirming header/toolbar scope and resolution order, (b) Nova 5.11.0 compatibility proven in a branch, (c) all calls behind one internal adapter, (d) a config allowlist for view-name resolution, (e) one rendering test per dynamic view, (f) a feature flag with one-line fallback to stock Nova chrome, and (g) a named owner with pin/fork/drop decided upfront. Do not approve as a dependency for customer-facing surfaces, and do not let the description's field-visibility claims onto a roadmap until source review confirms they exist. The opportunity score (41.61) reflects a real, common admin-UX need; the adoption signal (10 stars, 0 dependents, no vendor) says we are buying a shortcut for internal tooling, not a platform commitment.
How can I help you explore Laravel packages today?