outl1ne/nova-sortable
Laravel Nova package that adds drag-and-drop reordering to resource index and HasMany views, powered by Spatie's eloquent-sortable. Supports pivot tables, move-to-start/end arrows, per-resource sorting control, and localization.
Architecture fit
spatie/eloquent-sortable, which is already a de facto standard in the Laravel ecosystem.Sortable trait, a sort_order column is added, and NovaSortable is dropped into the resource definition. No changes to APIs, queues, or domain services are required.laravel/nova:^5.0 and transitively to a specific spatie/eloquent-sortable major. Both are upgrade-sensitive.Integration feasibility
UPDATE ... SET sort_order = id) and deciding the correct sortable scope (global vs. per-parent/per-category), which is where most misconfigurations occur.sort_order column and careful scope definition.Technical risk
dependents: 0 figure is likely an artifact of Nova's closed ecosystem and should not be read as zero adoption.sort_order produces non-deterministic ordering, which surfaces as "phantom bugs" in the admin UI.Key questions
created_at-based ordering we'd be replacing?Stack fit
eloquent-sortable is already present; otherwise it becomes a new transitive dependency pinned by the package.Migration path
id/created_at) per resource — this defines "correct" before and after.sort_order as a nullable integer, backfill deterministically (copy id or created_at rank), then enforce non-null and add a composite index on (scope_column, sort_order).Spatie\Sortable\Sortable on the model, define $sortable scope columns, and register NovaSortable in the resource.Compatibility
^5.0 and PHP >=8.1. Verify the pinned spatie/eloquent-sortable major is compatible with the app's Laravel version before committing.Sequencing
id).Maintenance
eloquent-sortable major becomes a coordinated upgrade.composer.json and track the package's changelog; a single-maintainer MIT package should not be allowed to float.Support
Scaling
eloquent-sortable rewrites only the rows between the old and new positions, so per-move cost scales with drag distance, not total table size. Lists in the low thousands are typically fine; tens of thousands are not appropriate for drag-and-drop UX regardless of package.(scope, sort_order) index up front — missing it turns every reorder into a table scan on the scoped set.Failure modes
sort_order values → non-deterministic display order.Ramp-up
How can I help you explore Laravel packages today?