summerblue/administrator
summerblue/administrator is a Laravel admin panel package for quickly building backends with CRUD screens, form and grid builders, authentication, permissions, menus, and dashboard widgets. It streamlines common administrative interfaces with customizable, reusable components.
Install the fork with Composer and let Laravel's package discovery register the service provider (on older Laravel versions, add Frozennode\Administrator\AdministratorServiceProvider and the Administrator alias manually):
composer require summerblue/administrator
Publish the config, assets, and language files. Run php artisan vendor:publish and choose the Administrator provider (or use its tags, typically config, assets, and lang). You should end up with:
config/administrator.php — global settings: title, route path/prefix, login/logout paths, menu, and the permission closure.config/administrator/*.php — one file per Eloquent model.public/packages/... (or public/vendor/...) — the admin CSS/JS.Open config/administrator.php first. Set the route path, confirm the permission closure (the default is usually just "is authenticated" — tighten it to an admin check), and leave menu empty initially so every model config appears in the sidebar automatically.
Create your first model config at config/administrator/posts.php:
return [
'title' => 'Posts',
'single' => 'post',
'model' => App\Models\Post::class,
'columns' => ['id', 'title', 'author.name', 'created_at'],
'edit_fields' => [
'title' => ['title' => 'Title', 'type' => 'text'],
'body' => ['title' => 'Body', 'type' => 'textarea'],
'author' => ['title' => 'Author', 'type' => 'relationship', 'name_field' => 'name'],
],
'filters' => [
'title' => ['title' => 'Title'],
],
'rules' => ['title' => 'required|max:255'],
];
Then visit /admin, log in with an existing user, and you have working list/create/edit/delete screens. Your first real use case is almost always "replace a pile of hand-written CRUD controllers for internal back-office tables" — start with the two or three models support staff touch most.
One config file per model, treated as a first-class artifact. Keep them in version control alongside migrations. The single key drives user-facing messages ("post created"), so name it as the lowercase singular noun.
Formatting columns with output closures. Rather than exposing raw IDs or timestamps, use per-column closures to render badges, links, or computed values. This is the main lever for making the auto-generated list view readable without touching views:
'columns' => [
'title' => ['output' => function ($post) {
return "<a href='/posts/{$post->id}'>{$post->title}</a>";
}],
],
Scoping and eager loading through query_filter. The most valuable extension point for multi-tenant or role-scoped admin panels. It receives the query builder, so use it both to restrict rows and to with() relationships referenced in columns:
'query_filter' => function ($query) {
$query->where('team_id', auth()->user()->team_id)->with('author');
},
Relationships as edit fields. Use the relationship method name as the key, 'type' => 'relationship', and name_field. This gives you searchable selects without writing option-loading code. For many-to-many, the field writes through the relationship automatically; keep pivot columns in mind.
Bulk actions for operational workflows. Define an actions array whose action closure receives the filtered query. This is the natural home for "publish selected", "recalculate", "export CSV" — anything an ops team would otherwise ask you to script.
Customize the model_handler for cross-cutting save logic. Slugs, audit rows, cache invalidation, and event dispatch belong here (or in model observers), not scattered across configs. Overriding the handler once keeps every model consistent.
Menu config as information architecture. Once you have more than a handful of models, stop relying on auto-listing and define a nested menu array grouping content, commerce, and settings. It is the difference between a usable back office and a wall of links.
Views and language files are publishable. Override the package views for branding and the language files (this fork ships Chinese translations) for localization. Treat published views as yours to maintain across upgrades.
config:cache and closures. The permission closure and any closures in config/administrator.php cannot be serialized by php artisan config:cache. If caching is mandatory in production, move logic into invokable classes or gates rather than closures, and test a cached boot before deploying.public/ is the most common "the admin looks broken" report. Clear public/vendor assets and php artisan view:clear after composer update.composer show summerblue/administrator and scan the repo's branches — the 2024 release may target a specific Laravel major. Pin the package in composer.json.permission to an explicit admin/role check, and consider an auth middleware plus a separate guard so admin routes are unreachable to normal users even if they guess the path.unique:posts,slug will reject the record against itself. Use a Rule::unique(...)->ignore($id) form (or an equivalent closure) and verify against the version you installed.edit_fields keys must be fillable or relationships. Mass-assignment exceptions and silently ignored fields usually mean the attribute isn't in $fillable or the relationship method name is misspelled.location directory, a naming strategy (random plus a length is safer than original), and a URL that actually resolves to the file (public path vs. storage:link). Test upload and display; they fail independently.where clauses; index every column you expose as a filter. For relationship filters, filter on the foreign-key column, not the related table, unless you know the join is generated./{slug}), register the admin prefix before it or the admin URLs will be swallowed.web middleware group, producing CSRF failures or lost flash messages. Check route:list and the groups in the service provider.menu array is excluding it.restore is exposed via a custom action if you need it.How can I help you explore Laravel packages today?