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 Perspectives Laravel Package

norman-huth/nova-perspectives

Save and switch between named perspectives of your Laravel Nova resources. Capture filters, sorting, and column settings as reusable views so teams return to the exact index configuration they need without reconfiguring tables.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a small Nova add-on from Norman Huth that layers named "perspectives" on top of a Nova resource index — a saved bundle of filters, sorting, and (depending on config) column/search state that a user can pick from a dropdown instead of re-applying the same filter set every visit. It has ~5 stars and no dependents, but v1.3.0 changes its status: Nova 5 support landed (PR #13) and an external contributor added a redirect-to-resource feature (PR #12). Treat it as a short, vendored utility — pin the exact version and read src/ before you build on it, but it is no longer correct to assume it's frozen.

Minimal steps:

  1. composer require norman-huth/nova-perspectives:1.3.0 — pin the exact version. Note the repo mixes tag styles (1.1.2, v1.2.0, v1.3.0), so a floating constraint can resolve surprisingly; pin and check composer.lock.
  2. Publish config + migration and migrate — perspectives persist per user/resource:
    php artisan vendor:publish --provider="NormanHuth\NovaPerspectives\NovaPerspectivesServiceProvider"
    php artisan migrate
    
    If you already published the migration on 1.1.x/1.2.x, vendor:publish will not overwrite it. Diff the package's migration against yours — v1.3.0's redirect feature likely needs a new column, and you'll need a hand-written follow-up migration.
  3. Read config/nova-perspectives.php for the model binding, table name, per-resource toggles, and any new redirect keys.
  4. Grep the service provider for the registered trait/field, then wire it into one noisy resource (Order, Invoice, 10+ filters) as the first use case: "Unpaid, this quarter" for accounting, "Assigned to me, open" for support.

Where to look first: README.md for intended DX, src/ for the resource entry point (trait vs. field class), the migration for the persisted shape, and PR #12 + PR #13 diffs — they're the only changelog detail you get for the two new behaviours.

Implementation Patterns

Per-resource opt-in. Add the trait/field to one resource at a time. Each resource has its own filter semantics, and a bad default perspective is worse than no perspective.

Perspective-as-default vs. perspective-as-choice. (a) Seed a perspective per role so the index always opens pre-filtered — needs a seeder/job writing rows after User::create; (b) let users save ad-hoc combinations — needs only the UI. Ship one or the other; mixing them leaves users unable to tell whose view they're looking at.

Redirect-to-resource (new in 1.3.0). PR #12 adds a redirect target to a perspective, which turns a perspective from "filtered index" into "jump-off point" — e.g. a "Failing jobs" perspective that navigates straight to a specific resource or record context. Read src/ to confirm whether the target is a hardcoded URL, a Nova resource class, or a route name, then:

  • Validate the target server-side (allow-list of resource classes/routes) so a saved perspective can't become an open redirect.
  • Check the redirect target's own authorizable()/policy — a perspective must not become a way to reach a resource the user can't view.
  • Don't overload it: users expect the perspective dropdown to filter the current index. Put redirecting perspectives in a clearly labelled group or a separate nav menu item.

Compose with Nova's native filters. Perspectives rehydrate the filter bar (typically via query string), so a perspective is a shortcut into existing filter state, not a replacement for filters(). Keep filter classes the single source of truth; a filter rename then breaks one config line instead of silently corrupting saved rows.

Deep links for free. State rides in the URL, so a perspective is shareable — paste the index URL into a ticket and the recipient lands on the same slice. Great for support ("here's the view with the failing jobs").

Multi-tenant guard. If perspectives are keyed by user only, one tenant's saved filter can leak naming/IDs into another. Scope by tenant (team_id on the published migration) or key by user and team.

Integration with indexQuery. If you override indexQuery(), verify perspective constraints still apply — the package usually injects through the request, so a manual where can shadow or be shadowed. Assert with a feature test.

Gotchas and Tips

1.2.x → 1.3.0 is an upgrade, not a drop-in if you maintain a fork. If you vendored the package into packages/ because of the archival, diff src/ against 1.3.0 before deciding to keep the fork. The Nova 5 work (PR #13) touches the front-end/request layer; re-applying your local patches blindly will regress it. Prefer config/model extension points over edits wherever possible.

Nova 5 asset and cache changes. Nova 5 rewrote the front-end and its asset pipeline. After upgrading, republish the package's assets (php artisan vendor:publish --tag=… per its README or nova:publish) and clear config/route/view caches — a stale compiled JS bundle is the classic "dropdown renders but nothing happens" symptom. Test on Nova 5 with a fresh browser session, not your dev profile.

Read the migration before trusting it. With a new column in play, run php artisan migrate:status and inspect the schema to confirm what actually landed. If the package's migration is idempotent-guarded (hasColumn), re-publishing may be a no-op; if it isn't, you may get a duplicate-column error mid-deploy.

Authorization is on you. Perspectives are DB rows referenced by ID. Confirm the package checks ownership before applying one — if it doesn't, a user can load another user's perspective by guessing an ID. An auth()->id() scope in the model or a policy is the cheapest fix; do it before shipping. Same for the new redirect target.

Nova's own column state fights it. A perspective that also sets columns can be overridden by Nova's stored per-user column preference, producing "I applied the perspective and half the columns are still hidden." Test with a fresh user and a returning user — they behave differently.

Stale state after filter changes. Renaming or deleting a Nova filter leaves orphaned perspective rows that 500 or silently no-op. Add a cleanup command, or wrap the apply step so unknown filters are skipped rather than thrown. With redirects added, also handle a deleted/renamed resource class in a stored target.

Debugging. php artisan route:list | grep -i perspective confirms routes; the config's model binding, cache key, and table name are the usual culprits. Check storage/logs/laravel.log for a swallowed exception — this class of package tends to catch and return the unfiltered index.

Extension points. The config's model binding lets you subclass Perspective to add columns/relationships; the trait can be overridden per resource to define eligible filters. Both survive version bumps better than patching src/.

Test it in a browser. The behaviour is "index page + query string + redirect," which unit tests miss. One Dusk/browser test per scenario — filter perspective yields the expected row set, redirect perspective lands on the expected resource — pays for itself the first time a Nova upgrade shifts request handling. Re-run those tests as the primary gate on the 1.3.0 upgrade.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core