Admin shell, contextual navigation, and encrypted general settings for Laravel Livewire packages.
composer require nuewire/platform:^2.1
php artisan migrate
php artisan optimize:clear
Open /admin. The route prefix and middleware are configured in config/nuewire/platform.php.
[Logo] Home Content Plugin Settings [Notification] [Theme] [User]
The notification action is rendered only when the host binds Nuewire\Platform\Contracts\NotificationProvider.
Navigation uses three levels:
Area → Group → Page
use Nuewire\Platform\Navigation\NavigationRegistry;
app(NavigationRegistry::class)
->registerArea('content', [
'label' => ['id' => 'Konten', 'en' => 'Content'],
'order' => 20,
])
->registerGroup('content', 'publishing', [
'label' => ['id' => 'Publikasi', 'en' => 'Publishing'],
'order' => 10,
])
->register('blog.posts', [
'area' => 'content',
'group' => 'publishing',
'slug' => 'posts',
'label' => ['id' => 'Artikel', 'en' => 'Posts'],
'description' => ['id' => 'Kelola artikel.', 'en' => 'Manage posts.'],
'component' => 'blog::posts',
'permission' => 'posts.view',
'icon' => 'content',
'order' => 10,
]);
Page IDs should be namespaced, such as blog.posts, while URL slugs remain short. The optional aliases field supports redirects from old slugs.
Available conditional fields:
'visible' => fn (): bool => config('blog.enabled'),
'badge' => fn (): ?string => '3',
permission controls authorization. visible controls feature availability; it must not be used as a substitute for authorization.
/admin
/admin/content/{page-path}
/admin/plugin/{page-path}
/admin/settings/{page-path}
Page paths may contain validated lowercase segments, for example /admin/plugin/newsletter/subscribers. When a page is requested through an alias or the wrong legacy area, Platform redirects to its canonical URL.
<x-nuewire::admin title="Dashboard" :full-width="true">
...
</x-nuewire::admin>
<x-nuewire::admin
title="Posts"
active-area="content"
active-page="blog.posts"
>
...
</x-nuewire::admin>
<x-nuewire::guest title="Login">
... login form ...
</x-nuewire::guest>
The guest layout only renders the login UI. The host application keeps control of authentication.
The header theme control cycles through System, Light, and Dark. The selected mode is a personal browser preference stored under nuewire.theme. General Settings only defines the default used before the user chooses a mode.
<livewire:nuewire-platform />
Settings are encrypted at storage/app/private/.nuewire/platform.json. Version 2 reads the old theme key and migrates it to default_theme. The v1 navigation and sidebar_mode values are ignored because the new shell has a fixed header and contextual sidebar.
The profile and logout route names are configurable:
'user_menu' => [
'profile_route' => 'profile.edit',
'logout_route' => 'logout',
],
Missing routes are not rendered.
php artisan vendor:publish --tag=nuewire-platform-config
php artisan vendor:publish --tag=nuewire-platform-views
php artisan vendor:publish --tag=nuewire-platform-translations
See the suite migration guide at docs/NAVIGATION_V2.md.
Platform 2.1 registers the full-width Home page as the nuewire-dashboard Livewire component.
php artisan migrate
php artisan nuewire:acl:sync # when ACL is installed
php artisan optimize:clear
Layout resolution is:
User layout → Role preset → Platform default → Registry default
The editor is available directly on the dashboard and supports drag ordering, controlled 12-column widths, add/remove, widget settings, mandatory widgets, reset, role preview, and JSON import/export.
Register a standard widget from any package:
use Nuewire\Platform\Dashboard\DashboardRegistry;
use Nuewire\Platform\Dashboard\WidgetContext;
app(DashboardRegistry::class)
->registerGroup('publishing', [
'label' => ['id' => 'Publikasi', 'en' => 'Publishing'],
'order' => 20,
])
->register('blog.posts-total', [
'group' => 'publishing',
'label' => ['id' => 'Total Artikel', 'en' => 'Total Posts'],
'description' => ['id' => 'Jumlah artikel.', 'en' => 'Number of posts.'],
'type' => 'stat',
'permission' => 'posts.view',
'width' => 3,
'default' => true,
'cache_ttl' => 300,
'cache_scope' => 'global',
'resolver' => static fn (WidgetContext $context): array => [
'value' => number_format(Post::query()->count()),
'url' => $context->route('content', 'posts'),
],
]);
Standard types are stat, status, chart, table, feed, actions, and custom. Layout JSON stores only IDs, widths, positions, and validated settings—not PHP classes, queries, permissions, or closures.
Commands:
php artisan nuewire:dashboard:list
php artisan nuewire:dashboard:reset --user=123
php artisan nuewire:dashboard:reset --role=administrator
php artisan nuewire:dashboard:reset --platform
php artisan nuewire:dashboard:export --role=administrator --path=dashboard.json
php artisan nuewire:dashboard:import dashboard.json --role=administrator
php artisan nuewire:dashboard:clear-cache
See docs/DASHBOARD.md in the suite for the widget catalog, sizing guide, security model, and upgrade procedure.
How can I help you explore Laravel packages today?