Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Open Admin Laravel Package

open-admin-org/open-admin

Open Admin is a Laravel admin panel and CRUD scaffolding package for building data-driven backends quickly. It includes model grids, forms, filters, actions, authentication, menus, widgets, and extensible components for managing models with minimal code, plus role-based access, media tools, and flex...

View on GitHub
Deep Wiki
Context7

Getting Started

open-admin-org/open-admin is a drop-in-ish admin panel for Laravel, forked from z-song/laravel-admin but stripped of jQuery and rebuilt on Bootstrap 5 + vanilla JS. The public API (Grid, Form, Show, Tree, Actions, Admin facade) is intentionally close to laravel-admin, so most existing documentation and Stack Overflow answers for "laravel-admin" still translate — minus the jQuery-specific bits.

Minimum setup

composer require open-admin-org/open-admin
php artisan admin:install        # publishes config, runs migrations, seeds admin user + menu
php artisan storage:link         # if you plan to use file/image uploads

After install, log in at /{admin_prefix}/auth/login (default credentials are admin / admin — change them immediately).

Where to look first

  • config/admin.php — route prefix, auth guard, database connection, upload disks, middleware stack, extensions. This is the file you will revisit most.
  • app/Admin/routes.php — admin routes are registered here, not in routes/web.php.
  • app/Admin/bootstrap.php — global bootstrapping for the admin app: registering extensions, injecting assets, tweaking navigation.
  • app/Admin/Controllers/ — every generated controller (HomeController, AuthController, your CRUD controllers) lives here.
  • database/migrations/ published by admin:install — admin_users, admin_menu, admin_permissions, admin_roles, admin_operation_log, etc.

First use case: scaffold one model

php artisan admin:make PostController --model=App\\Models\\Post

Then edit app/Admin/Controllers/PostController.php and fill in grid() and form():

protected function grid()
{
    $grid = new Grid(new Post);
    $grid->column('id')->sortable();
    $grid->column('title')->filter('like');
    $grid->column('published_at')->sortable();
    return $grid;
}

protected function form()
{
    $form = new Form(new Post);
    $form->text('title')->rules('required|max:255');
    $form->textarea('body');
    $form->datetime('published_at');
    return $form;
}

Add the route in app/Admin/routes.php ($router->resource('posts', PostController::class);) and the CRUD UI is live. That is your first "this package pays for itself" moment.

Implementation Patterns

Grid is the workhorse. Treat grid() as the place where you decide list-page performance and usability:

$grid->model()->with(['author', 'category'])->where('status', 'published');
$grid->column('author.name');                    // eager loaded, no N+1
$grid->column('title')->display(fn($t) => Str::limit($t, 60));
$grid->column('status')->using([0 => 'Draft', 1 => 'Live'])->label();
$grid->filter(fn($f) => $f->like('title'));
$grid->actions(fn($a) => $a->disableDelete()->disableEdit());

Common additions: $grid->exporter(new PostExporter), $grid->quickSearch('title'), $grid->disableRowSelector(), $grid->paginate(50).

Forms follow the same field-builder idiom. The most-used patterns:

  • Field-level validation: $form->text('email')->rules('required|email|unique:users,email').
  • Pre-save mutation: $form->saving(fn(Form $f) => $f->model()->slug = Str::slug($f->title));
  • Post-save hooks: $form->saved(fn($form) => ...) and $form->submitted(...).
  • Relations: $form->select('author_id')->options(User::pluck('name','id')), $form->multipleSelect('tags'), $form->hasMany(...).
  • Layout: $form->tab(...), $form->step(...), $form->row(...) to break long forms into blocks.

Custom actions (RowActions, BatchActions, Actions) are where admin panels earn their keep. Put business logic in an Action class, not a controller — they are self-contained, reusable, and can render their own modal/drawer:

$grid->actions(fn(Actions $a) => $a->add(new PublishPost()));

Dashboard + widgets. Override HomeController::index() to compose Box, InfoBox, Chart, Card, Table widgets. Add global CSS/JS via Admin::css() / Admin::js() / Admin::script() inside app/Admin/bootstrap.php or per-controller.

Auth, roles, and audit. Roles and permissions are database-backed (admin_roles, admin_permissions, admin_role_permissions, admin_role_users). Bind permissions to routes in the admin UI, then check in code with Admin::user()->can('posts.edit') or Admin::user()->inRoles(['editor']). Enable config('admin.enable_operation_log') if you need an audit trail of model writes — useful but noisy, so scope it per-controller.

Extensions ecosystem. laravel-admin-compatible extensions typically ship a ServiceProvider that calls things like Admin::extend() / Admin::import(). Because open-admin kept the Encore\Admin namespace (check composer.json for the exact namespace on your pinned version), many of these still load — but any extension that touches jQuery will need a rewrite. Prefer extending by writing your own Action/Widget classes over pulling in old extensions.

Upgrade/migration workflow. Since this is a fork of a previously maintained package, pin a version in composer.json, run php artisan admin:publish --force after upgrades only if you have not customized the assets, and keep config/admin.php under version control so config drift is visible in diffs.

Gotchas and Tips

The jQuery removal is the #1 compatibility trap. Third-party laravel-admin extensions, custom Admin::script() snippets, .datepicker(), .select2(), .sortable() calls — none of these work unless the fork or your own code replaced them. Search the package's resources/ for the vanilla-JS replacements before assuming a feature is missing. When porting a snippet, translate $(el).on('click', ...) to el.addEventListener('click', ...) and jQuery-AJAX to fetch/axios.

Bootstrap 5 class renames will silently break custom views. If you have any Blade templates or view overrides, rewrite float-right → float-end, ml-* → ms-*, pl-* → ps-*, data-toggle → data-bs-toggle, data-target → data-bs-target. Old markup won't error; it'll just render wrong, which is harder to spot.

config/admin.php is cached. If php artisan config:cache has run, edits to route prefix, middleware, or upload disks won't take effect until php artisan config:clear. Same with route:clear after adding a route in app/Admin/routes.php.

Menu is database-driven, not file-driven. Adding a route doesn't add a sidebar link. Either use the admin UI's Menu section, or add the entry to app/Admin/bootstrap.php via Admin::menu(). After moving between environments, php artisan admin:import is the usual fix for an empty/mismatched menu.

Watch N+1 in grids. $grid->column('author.name') without $grid->model()->with('author') fires a query per row. On a 100-row page that's 100 queries. Always eager-load relations you display or filter on, and be aware that ->display(fn() => ...) callbacks execute per-row too.

Uploads need three things aligned: a valid storage (or S3) disk in config/filesystems.php, the corresponding upload config block in config/admin.php, and the public/storage symlink. Missing any of the three yields confusing "file saved but broken image" behavior.

Operation logging can balloon your DB. If enable_operation_log is true, every admin write is logged with a serialized payload. Fine for compliance, painful for high-traffic admin panels — disable globally and enable per-controller/model where required, or rotate the table.

Laravel version support is the biggest real-world risk. Because the upstream was archived and this is a fork with a modest community, the package's Laravel compatibility is narrower than what composer.json might suggest in practice. Before a Laravel major upgrade, check the fork's releases and test the admin login, one Grid, one Form, and one upload flow — those four cover the usual breakage points.

Debugging admin issues is mostly "look in the right place." For 404s: check config('admin.route.prefix') and app/Admin/routes.php. For 403s: roles/permissions tables and Admin::user()->can(...). For blank grids: PHP error swallowed by the response layer — check storage/logs/laravel.log first, then config('app.debug'). For stuck assets: php artisan admin:publish --force and hard-refresh with cache disabled.

When in doubt, search upstream docs. Errors and configuration keys are overwhelmingly shared with laravel-admin; searching for the upstream term returns many more results than searching for "open-admin". Just filter the answers mentally — anything involving jQuery, Select2, or old Bootstrap classes needs translation to this fork.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect