Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Dynamic Views Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Confirm the target before you install. v2.4.0 is a one-line compatibility bump for Nova 5.11.0. The changelog says nothing about earlier Nova versions, so check your Nova constraint first. If you are not on Nova at all, this package has no use to you.

composer require shuvroroy/nova-dynamic-views

Pin it ("shuvroroy/nova-dynamic-views": "2.4.*") — with 10 stars and zero dependents there is no community buffer between you and a surprise minor.

2. Reconcile the scope before writing code. The repo framing and release notes describe a header/toolbar override helper. The marketplace copy promises condition-driven field visibility, form/detail view switching, and context-aware layouts. Those are different products. Read src/ and the service provider in one sitting — it is a small package — and treat the header/toolbar framing as authoritative until the source proves otherwise. Ten minutes here prevents building a feature on a promise the package does not keep.

3. Publish and clear.

php artisan vendor:publish --provider="ShuvroRoy\NovaDynamicViews\NovaDynamicViewsServiceProvider"
php artisan view:clear

Note what actually landed — config file, views, nothing. Auto-discovery handles the provider unless you have it disabled.

4. Read the resolution order. This is the single most important thing to learn: global default → per-resource override → conditional override. Every confusing behaviour you will hit later traces back to a misunderstanding of which of those three won.

5. First use case — one resource, one branch. Take User. Replace its toolbar with a branding bar plus two quick links. Then open a resource you did not touch and look at it. If it changed too, your registration is global rather than scoped — that surprise at minute ten is far cheaper than at sprint end.

6. Document the native fallback on day one. Nova's own header() / toolbar() on the resource, plus Nova::header(fn () => view(...)) in NovaServiceProvider, cover most single-override needs. Keeping that path written down makes removing this dependency a refactor rather than a rewrite.

Implementation Patterns

Global default plus surgical overrides. The entire value proposition is de-duplication. Register one generic default — environment badge, tenant name, support link — and override only where a resource genuinely diverges. If you catch yourself writing the same override on five resources, you have a missing global default, not five overrides.

Wrap every call in one internal adapter. This is the most important pattern in the whole package. Do not scatter package calls across forty resources:

namespace App\Nova;

class NovaChrome
{
    public static function headerFor(string $resource): void
    {
        // delegate to shuvroroy/nova-dynamic-views here, and only here
    }

    public static function toolbarFor(string $resource): void
    {
        //
    }
}

Give it your own vocabulary. If the package stalls, you rewrite one file. Cheapest insurance available.

Resolve conditions in PHP, not Blade. Instead of @if(auth()->user()->hasRole('admin')) inside a header partial, decide which view in the registration callback and let each Blade file stay dumb:

// conceptually — verify exact signatures against src/
if (auth()->user()->hasRole('tenant-admin')) {
    // resolve tenant-scoped header view
} else {
    // resolve default admin header view
}

Role, permission, and tenant checks belong in PHP where they are testable. Layout belongs in Blade.

Compose from partials, not copies. Have each dynamic view include reusable pieces (<x-nova.env-badge />, <x-nova.tenant-switcher />, <x-nova.quick-links />). You get per-user and per-tenant variation without maintaining N nearly identical header files.

Multi-tenant scoping through an explicit allowlist. Resolve the tenant before the view is chosen, and map identifiers through config — never through string concatenation:

// config/nova-chrome.php
return [
    'headers' => [
        'acme'    => 'nova.headers.acme',
        'globex'  => 'nova.headers.globex',
        'default' => 'nova.headers.default',
    ],
];

This is where a "dynamic view" package can genuinely hurt you: never let a tenant slug or route parameter flow directly into a view name.

Smoke-test rendered output, one test per view.

$this->actingAs($admin)
    ->get('/nova/resources/users')
    ->assertOk()
    ->assertSee('Production');

There are no public failure reports for this package, so your suite is the documentation of expected behaviour — and it is what catches a Nova minor bump silently changing resolution.

Feature-flag the rollout. NOVA_DYNAMIC_CHROME=false falling back to stock Nova chrome gives you a one-line rollback without redeploying application code.

Version-bump ritual. Every Nova upgrade gets a manual pass through each dynamic view in staging before production. Nova minors have changed view-resolution behaviour before, and there is no vendor support to catch it for you.

Gotchas and Tips

  • Precedence is the bug you will actually hit. A header appearing where you did not expect it means a global registration is beating (or being beaten by) a resource-level one. Drop a temporary Log::debug() around the resolved view name and the condition that matched, reproduce, delete. On a codebase this small that beats hunting through issues.
  • php artisan view:clear on every deploy that touches views. A stale compiled view is the classic "works locally, wrong on staging" failure. Put it in your deploy script next to config:cache.
  • Header ≠ toolbar. Separate Nova slots with different spacing and responsive behaviour. A component that looks right in one will often look wrong in the other. Check both at narrow widths before signing off.
  • Keep header partials cheap. Nova renders headers and toolbars on every index, detail, and form page. An Eloquent count or an outbound HTTP call in a header quietly taxes the whole admin panel. Cache it or hardcode it.
  • The package owns the view slot, not your assets. Custom JS/CSS needs your own Vite build or explicit Nova::script() / Nova::style(). Nothing is compiled for you.
  • Treat view-name input as untrusted. Anything user-supplied reaching the resolver is a path-traversal and cross-tenant-leak surface. Always resolve through the config map.
  • The service provider is the extension point. Conditional resolution, logging, and defaults all converge there. Read it once and you understand the entire package.
  • Do not over-trust the description. If you were sold on field visibility and form switching, verify those exist before planning around them.
  • Pin and expect to own it. No SLA, no security guarantee, one maintainer. Budget for pin, vendor, or fork, and keep the native Nova::header() / resource header() fallback documented so removal stays a refactor.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core