xn/laravel-admin
A Laravel admin panel package for building management dashboards with CRUD screens, authentication, and common admin tooling. Suitable for adding a ready-made backend interface to Laravel apps; review its docs and compatibility before use.
Prerequisites. Confirm in the repo's composer.json which Laravel and PHP versions are supported before installing — with a package this early-stage, the version constraint is the first thing that will bite you. Pin explicitly:
composer require xn/laravel-admin:"^1.0" --with-all-dependencies
Install and publish. Typical Laravel admin packages ship a service provider that auto-registers, plus publishable config, migrations, and assets:
php artisan vendor:publish --provider="Xn\LaravelAdmin\LaravelAdminServiceProvider"
php artisan migrate
php artisan admin:install # or equivalent; check README for the exact command
If the publish step exposes tagged groups (--tag=admin-config, --tag=admin-assets), publish them separately so you know exactly what landed in your app.
Where to look first, in order:
README.md — install path and the one canonical example.config/admin.php (after publishing) — route prefix, middleware stack, auth guard, database connection, upload disk.routes/admin.php inside the package — the real surface area; this tells you what's actually implemented vs. aspirational.src/Http/Controllers/ and src/Models/ — base classes you'll extend.resources/views/ — what you can override by publishing views.First use case. Get a single CRUD screen working end-to-end before touching anything else: a Post model with title/body/published_at. Register it as an admin resource, confirm list/create/edit/delete all work, then confirm you can customize one field. That one vertical slice will expose 80% of the package's conventions (and its rough edges) in an hour.
Extend, don't fork. Most packages in this category give you a base controller or a resource-registration array. The sustainable pattern is:
class PostController extends AdminController
{
protected function resource(): string { return PostResource::class; }
}
and declare fields in a dedicated resource/form class rather than in the controller. This keeps config out of routes and makes it easy to override if you later need to drop the package.
Keep admin routes on their own guard. Don't reuse the web guard. A dedicated admin guard with its own provider and session cookie means an admin compromise doesn't automatically hand over user sessions, and it makes Auth::guard('admin') unambiguous in middleware and tests.
Wrap package routes in your app's middleware. Whatever the package registers, apply your own stack on top in RouteServiceProvider or the published route file: throttle:admin, audit-log middleware, EnsureTwoFactor. Packages rarely ship these.
Integration tips for a real app:
spatie/laravel-permission against the admin guard. Model policies will usually work if you point Auth::getDefaultDriver() at the admin guard inside admin controllers only — do this in a middleware, not globally.FILESYSTEM_DISK. Use a distinct admin-uploads disk pointing at S3 or a private local path, and serve through signed URLs.Testing pattern. Feature-test the admin routes with the correct guard:
$this->actingAs($admin, 'admin')
->get('/admin/posts')
->assertOk()
->assertSee('Posts');
Write one smoke test per resource. It catches broken publishes, guard regressions, and route-cache issues in CI far cheaper than manual clicking.
Low adoption means you are the QA. Zero dependents and zero stars is not disqualifying, but it does mean: read the source of the install command before running it, and vendor-pin the exact version in composer.json — no ^ if you can avoid it. Treat every minor release as potentially breaking.
Publishing is a one-way copy. vendor:publish copies files into your app; upstream fixes won't reach published views or config. Publish only what you intend to own (usually config and views), leave the rest in vendor/.
Config caching will surprise you. Any closure or env() call inside config/admin.php breaks under php artisan config:cache. Check for this early — it's the single most common production-only failure in admin packages, and it manifests as a blank dashboard or "not authenticated" loop.
Guard and redirect loops. If /admin bounces to login forever, check three things in order: the admin guard is defined in config/auth.php; the login controller points at that guard; and the middleware stack doesn't include the package's auth middleware and your own auth middleware with different guards.
Route caching. php artisan route:cache fails or silently drops admin routes if the package registers closures or uses non-cacheable route definitions. Reproduce with route:cache locally before deploying. php artisan route:list --path=admin is your fastest sanity check.
Migration collisions. Packages that create a users table or add columns to it will collide with your app. Publish migrations, open them, and edit before running. If the package's admin:install also seeds a superuser, change that password in the seeder — never leave the documented default.
Assets. If the admin UI looks unstyled in production but fine in dev, it's almost always a published-asset path or a public/vendor/... directory that didn't get deployed. Add vendor:publish --tag=admin-assets --force to your deploy script, or symlink.
Debugging workflow. APP_DEBUG=true plus laravel/telescope scoped to admin routes will surface the package's queries and exceptions quickly. For anything the package swallows in a try/catch, drop a dd() into the vendor controller — faster than guessing, just remember to revert.
Extension points to prefer, roughly in order of safety:
resources/views/vendor/xn-admin/.Security checklist before shipping: admin prefix renamed from /admin; separate guard; rate-limited login; 2FA or SSO on the admin guard; uploads restricted by MIME and stored off the web root; no default seed credentials; audit logging on write operations. None of this will be in a low-adoption package by default — budget a day to add it.
How can I help you explore Laravel packages today?