marshmallow/nova-sortable
marshmallow/nova-sortable is a Laravel Nova package that adds drag-and-drop sorting to resources, letting you reorder records directly in Nova and persist their position through a configurable sort column.
Architecture fit. Unchanged and still favorable: a narrow, additive Nova index-view extension that persists an ordinal against a model column, with no core-domain or cross-service coupling. The v3.9.0 notes add one materially useful architectural fact — the ordering engine is spatie/eloquent-sortable, not bespoke logic. That reframes the package as a thin UI bridge (drag-and-drop → setNewOrder) over a mature, widely-deployed persistence trait. Net effect: slightly better fit, because the hardest correctness logic is library-owned and documented rather than hidden in a 0-star repo — but we now take a transitive dependency into the model layer, and ordering semantics become a function of the resolved Spatie major. The Nova-license and Nova-major-pin caveats still stand.
Integration feasibility. Mechanically the same: Composer install, publish assets, ordinal column, trait/scope, per-resource enablement. The important refinement is that scoping is our code, not the package's — spatie/eloquent-sortable implements tenant/parent scoping through buildSortQuery() (and order_column_name, sort_when_creating config) on the consuming model. That means the highest-severity failure mode (cross-tenant order corruption) is mitigated only if we override buildSortQuery correctly and the Nova index query is passed through. This was previously an open question about the vendor; it is now an implementation deliverable on our side, which is more controllable but also easier to get silently wrong.
Technical risk.
spatie/eloquent-sortable ^5.0" means the resolved behavior depends on the platform's Laravel/PHP versions. Two environments can legitimately resolve different Spatie majors from the same composer.json, producing different ordering behavior with no code change on our side. Pin via composer.lock and verify resolution, not constraints.lodash 4.18.1 — 4.17.21 is current; node-forge 1.4.0 — 1.3.1 is current; picomatch 2.3.2 — 2.3.1 is current). Either the notes are hand-edited/inaccurate or the pipeline is synthesizing them. Verify the tag, the diff, and the tarball against the registry before adopting.@stefvanesch); bus factor is still effectively one.BelongsTo) — unchanged; still the first thing to rule out.Key questions.
spatie/eloquent-sortable major resolves on our platform, and what changes between v4 and v5 in scoping, sort_when_creating, and write behavior?buildSortQuery() per resource, and does it cover tenancy, parent relations, and soft deletes?Stack fit. Unchanged: good for Laravel + Nova resources carrying a stored ordinal; poor for derived ordering (computed rank, relevance, alphabetical) or lists primarily consumed via APIs where order is a versioned domain concern. Classify each candidate resource as "stored ordinal," "derived," or "no ordering need" before committing.
Migration path. Still an experiment, not a dependency:
(scope_columns, order).buildSortQuery() explicitly per model — treat this as the primary engineering task, not configuration.buildSortQuery() survive — only the UI binding swaps.Compatibility. Pin both the Nova package and spatie/eloquent-sortable; commit and verify composer.lock in CI, and test resolution at both the lowest and highest supported Laravel/PHP. Validate on a production-shaped staging clone: multi-tenant rows, soft-deletes, a parent/child resource, and every database engine in use. Add an explicit deploy step that republishes assets and asserts no stale bundle remains in public/vendor/nova — this release is bundle-only churn, so it is exactly the release most likely to drift silently.
Sequencing.
buildSortQuery().Maintenance. Slightly better than previously assessed: the ordering logic has a real upstream with documentation and a release history, and the dependabot merges — several of them security-driven (node-forge, follow-redirects, serialize-javascript, minimatch) — are evidence someone is tending the asset toolchain. But the bumps confirm the bundle is rebuilt frequently, so each upgrade requires an asset re-publish and a visual smoke test. Budget a few hours per quarter, plus a checkpoint at every Nova major and every Spatie major.
Support. No vendor SLA, but the escalation path now has a real terminus: Spatie's package for ordering semantics, our own code for buildSortQuery() and the Nova binding. Document the ordering policy and the per-model scope query internally so support can answer "why is this row here" without reverse-engineering a third-party bundle.
Scaling. Unchanged in shape: cost scales with rows whose positions shift, not with drags. Because upstream ordering writes are per-model rather than one bulk statement, large reorders hold locks longer — acceptable at admin scale (thousands of rows), risky beyond. Read paths are unaffected.
Failure modes.
buildSortQuery() → cross-tenant ordering corruption. Highest severity; now our defect, not the vendor's.Ramp-up. Developer ramp-up remains hours; familiarity with spatie/eloquent-sortable is common, which lowers it slightly. Product/admin ramp-up still requires a written ordering policy (what "order" means per resource, who may change it, what happens on create). Keep the reorder audit trail from day one.
How can I help you explore Laravel packages today?