m2mtech/ux-navigation
m2mtech/ux-navigation is a Laravel package for defining and rendering application navigation menus, with helpers for links, active states, and shared nav configuration across Blade views. It aims to keep navigation consistent and easy to maintain.
This assessment covers v2.0.0, which is a major release with breaking changes — treat the upgrade as a migration, not a composer update. Start with the UPGRADE.md/CHANGELOG and the diff of the renamed bundle namespace before touching application code.
Minimal steps for a Laravel app:
composer require <vendor>/<package>:^2.0
php artisan vendor:publish --tag=<package>-config # verify the tag name; it may have changed with the bundle rename
php artisan migrate # only if the package ships migrations
php artisan optimize:clear
Where to look first, in order:
composer.json of the package — confirm the new package/bundle name and the PSR-4 namespace roots. The bundle rename almost always moves the root namespace.src/ — locate the classes now carrying the m2m* prefix. These are the ones your use statements, container bindings, and config references must point at.config/ — check for renamed config keys and any new keys for the dark-mode selector.resources/ — the dark-mode selector ships front-end assets; find the Blade component/directive and the CSS entry point.First use case to validate end-to-end: resolve one m2m*-prefixed class from the container, exercise the relationship it models, then render a view that includes the dark-mode selector and toggle it. That single flow touches every part of the release.
Container-first resolution of the renamed classes. Don't new the m2m* classes. Bind or resolve through the container so future renames stay a one-line config change:
public function __construct(private M2mRelatedItems $items) {}
If the package registers its own bindings, confirm they were updated in v2 — a stale binding pointing at the old class name is the most common post-upgrade 500.
Relationships. The m2m* prefix was added specifically to avoid collisions with other extensions, so any model, trait, or relation method exposing these types should be typed against the new names. Update Relation::morphMap() entries and any belongsToMany pivot table names if table names followed the rename.
Incremental upgrade shim. For a large codebase, land the upgrade in two PRs. PR one: add class_alias() calls (or a small compat.php autoloaded via composer.json files) mapping old names to new, plus a Rector rule or a scripted search-replace of namespaces. PR two: remove the aliases once static analysis is clean. This keeps CI green throughout.
Dark-mode selector. Wire it into Tailwind rather than fighting it:
// tailwind.config.js
darkMode: 'class',
Then persist the choice with Alpine + localStorage, applying the class to <html> so it applies before paint. If you use Livewire, keep the toggle in a client-side component and only round-trip to the server when you genuinely need the preference stored per user — otherwise every toggle costs a request. Add the selector's classes to safelist if they are constructed dynamically and not present in scanned templates.
Testing. Add one feature test asserting the m2m* classes resolve and the relationship returns expected rows, and one HTTP test asserting the selector markup renders. These two tests catch ~80% of regressions from this release.
^2.0 and read the upgrade guide first. The renamed bundle means the old package name may still resolve to v1 on Packagist; confirm you actually installed v2 and not a stale lock entry. Run composer show <vendor>/<package> and check the version string.config/ survive composer update but may reference removed keys or old class strings. After upgrading: php artisan config:clear && php artisan cache:clear && composer dump-autoload.vendor:publish without --force, the old views/assets remain in resources/views/vendor/... and silently shadow the v2 versions. Regenerate and diff, don't blindly force.m2m* rename will not be caught by tests that pass by accident. Names in string form — queued job payloads, cached serialized objects, morphMap values, config arrays, and database columns storing class names — will not fail at compile time. Grep the whole project (including database/, resources/, and cached payloads) for the old identifiers.<head>, or accept the flash. With Livewire wire:navigate, re-apply the class on navigation or the theme resets.EventServiceProvider and listen arrays explicitly.composer require <vendor>/<package>:^1.0 and restore published assets; the alias shim above makes this reversible with minimal churn.How can I help you explore Laravel packages today?