nuewire/users
User management for Laravel: a lightweight package for handling user accounts, profiles, and common authentication workflows with framework-native conventions. Early-stage project with no stars yet, so review the source and docs before using it in production.
Minimal path from install to a working user screen:
composer require nuewire/users:^1.3 — pin the exact minor you validate. The 1.3.0 release note is link-only, so treat the upgrade from 1.2.1 as unverified until you read the diff: git diff 1.2.1..1.3.0 -- composer.json database/ config/ src/.php artisan vendor:publish --provider="Nuewire\Users\UsersServiceProvider" (check composer show nuewire/users and bootstrap/providers.php for the real FQCN) and read the published migration and config before running migrate. This is the single highest-value five minutes you will spend: it tells you whether the package creates its own users table, alters yours, or expects one to exist.config/users.php (user model, table, fields, avatar disk), the migration(s), the Livewire components under src/ or resources/views/livewire/, then the published routes. The description promises "configurable user model," so the config's model key is the seam that decides everything downstream.Illuminate\Foundation\Auth\User or your app's App\Models\User. If it defines its own, you must either point config/auth.php at it or set the package config to your model — picking wrong here produces silent Auth::user() nulls rather than errors.can:manage-users gate. That is the smallest end-to-end slice: it exercises the model binding, the authorization hook, the avatar rendering, and the activity feed in one screen — so a failure points at a specific layer instead of the whole package.Do not adopt this into an app that already has a mature user domain (teams, tenants, SSO, soft-deleted accounts) without first reading the migration. The "0 stars, single-author, NOASSERTION license" profile means you are the QA team.
Bind the package to your model, not the reverse. The most maintainable pattern is: keep App\Models\User as the canonical model, add the package's trait/interface (whatever config/users.php names), and set the config's model key to App\Models\User. If instead you let the package own the model and extend it, every future column addition lives in your subclass and the package's migration drifts from your schema. Verify which direction the package supports before writing code.
Authorization via policies, not the package's built-in checks. The description advertises "Laravel-native authorization hooks." Register a UserPolicy and let both the package's components and your own controllers call $this->authorize(). Centralizing here means one place to audit — important for a package that can create, edit, and presumably delete accounts. If the components expose an authorize or can config callback, wire it to your policy rather than duplicating rules.
Custom fields as a configuration exercise, not a fork. For "extensible profiles and customizable fields," prefer the package's field configuration (published config or a fields() method) over editing vendor views. Typical shape:
// config/users.php
'fields' => [
'name' => ['rules' => ['required', 'string', 'max:255']],
'email' => ['rules' => ['required', 'email', 'unique:users,email']],
'job_title'=> ['rules' => ['nullable', 'string', 'max:120']],
],
Mirror those rules into your own FormRequest so API and Livewire paths validate identically. Divergent validation between the package's component and your controllers is the classic source of "it saved from the UI but 422'd from the API."
Avatar uploads: own the disk and the conversion. Point the package's avatar disk at a configured filesystem disk (public or S3), never the default local disk with a hardcoded path. Serve through a controller route if avatars are private, and constrain uploads (image, mimes:jpg,png,webp, max:2048) in your own validation layer — a user-management UI is a public-facing file upload endpoint in disguise, and the package's defaults may be permissive.
Wrap writes in your own service when side effects exist. If creating a user must also provision a tenant, send a welcome mail, or assign a default role, don't hang that logic off the Livewire component. Introduce an AccountProvisioner and call it from both the package's component hooks (via events/listeners) and your console commands, so php artisan users:import and the UI stay consistent.
Activity feed as a read model. "Detailed authentication activity" implies a log table. Treat it as append-only and query it through a scoped repository with pagination and an index on (user_id, created_at). Never render the full history in a Livewire component without pagination — an account with years of logins will otherwise hydrate thousands of rows into memory on every render.
Testing pattern. Because the package is thinly documented, build a small characterization suite around it: create/edit/delete a user, assert the avatar file lands on the fake disk, assert a non-authorized actor gets 403, assert the activity row is written on login. These tests are your upgrade insurance for 1.4 and beyond.
create_users_table migration and your app already has one, migrate will fail on a duplicate table or, worse, apply to a table with a different shape. Inspect the filename timestamp and either skip it or copy its columns into your own migration. Never run it blind on a database that already has users.NOASSERTION. Read the diff for changes to migrations, config keys, model contracts, and authorization behavior before upgrading anywhere.Auth::user() returning null, @can always true, or policies not firing usually means the package's model isn't the one your guard is configured to use. Verify with dd(config('auth.providers.users.model'), get_class(auth()->user())).composer.json for livewire/livewire constraints; if it wants v2 and you're on v3, components may mount but fail on lifecycle hooks. Run composer why-not livewire/livewire before installing.config/users.php, run php artisan config:clear. A stale bootstrap/cache/config.php is a frequent "my config change did nothing" cause in staging.vendor:publish --force in a later upgrade will overwrite your customizations. Keep a diff of published views in version control and re-apply; or keep customization in config and your own Blade wrappers instead.php artisan route:list | grep -i user and php artisan about to confirm the provider registered, then check storage/logs/laravel.log for Livewire hydration errors. Livewire failures surface as re-renders rather than exceptions, so the log is where the truth is.How can I help you explore Laravel packages today?