一键导入
moonshine-appearance-v3
Use when customizing MoonShine v3 layouts, menus, colors, icons, assets, pages, dark mode, branding, or overall admin panel design.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when customizing MoonShine v3 layouts, menus, colors, icons, assets, pages, dark mode, branding, or overall admin panel design.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when working on any MoonShine v3 admin panel task — setup, resources, fields, components, appearance, frontend, security, or advanced patterns. This is the single entry point that routes to specialized sub-skills.
Use when creating ModelResource, configuring CRUD operations, working with tables/forms/detail pages, adding filters, search, pagination, events, buttons, query modification, import/export, or metrics in MoonShine v3.
Use when working with MoonShine v3 authentication, authorization, login, guards, custom user models, Socialite, 2FA, JWT, role-based access, Laravel policies, auth pipelines, or middleware.
Use when installing, configuring, or bootstrapping a MoonShine v3 admin panel. Covers installation, configuration, routing, middleware, localization, and artisan commands.
Use when working with custom controllers, handlers, routes, type casts, notifications, testing, package development, CrudResource (non-Eloquent), artisan commands, or practical recipe patterns in MoonShine v3.
Use when building UI with FormBuilder, TableBuilder, layout components, modals, tabs, cards, action buttons, metrics, or any visual building block in MoonShine v3.
| name | moonshine-appearance-v3 |
| description | Use when customizing MoonShine v3 layouts, menus, colors, icons, assets, pages, dark mode, branding, or overall admin panel design. |
Covers layout templates, menu configuration, color theming, icons, asset management, dark mode, branding, and custom pages.
MoonShine provides two built-in layout templates:
theme-minimalistic class and overrides colors for a lighter lookThe selected layout is published at app/MoonShine/Layouts/MoonShineLayout.php and configured in moonshine.layout.
BaseLayout (abstract)
-> AppLayout (standard)
-> CompactLayout (compact/minimalistic)
-> BlankLayout (bare bones -- Head + Body only)
-> LoginLayout (authentication page)
// config/moonshine.php
'layout' => \MoonShine\Laravel\Layouts\AppLayout::class,
// Or via MoonShineServiceProvider
$config->layout(\App\MoonShine\Layouts\CustomLayout::class);
php artisan moonshine:layout MyLayout
This creates app/MoonShine/Layouts/MyLayout.php.
namespace App\MoonShine\Layouts;
use MoonShine\Laravel\Layouts\CompactLayout;
use MoonShine\UI\Components\Layout\Layout;
final class MoonShineLayout extends CompactLayout
{
protected function getFooterMenu(): array
{
return [
'https://example.com' => 'Custom link',
];
}
protected function getFooterCopyright(): string
{
return 'My Company';
}
public function build(): Layout
{
return parent::build();
}
}
Instead of rewriting build(), override individual component methods:
protected function getHeadComponent(): Head { /* ... */ }
protected function getLogoComponent(): Logo { /* ... */ }
protected function getSidebarComponent(): Sidebar { /* ... */ }
protected function getHeaderComponent(): Header { /* ... */ }
protected function getTopBarComponent(): Topbar { /* ... */ }
protected function getFooterComponent(): Footer { /* ... */ }
protected function getProfileComponent(bool $sidebar = false): Profile { /* ... */ }
protected function getContentComponents(): array { /* ... */ }
protected function getLogo(bool $small = false): string { /* ... */ }
protected function getHomeUrl(): string { /* ... */ }
Quickly inject components into Sidebar or TopBar without overriding build():
protected function sidebarSlot(): array
{
return [
Search::make()->enabled(),
];
}
protected function sidebarTopSlot(): array
{
return [
Notifications::make(),
];
}
protected function topBarSlot(): array
{
return [
// custom components in top bar
];
}
public function build(): Layout
{
return Layout::make([
Html::make([
$this->getHeadComponent(),
Body::make([
Wrapper::make([
$this->getTopBarComponent(),
// $this->getSidebarComponent(), // removed
Div::make([
Flash::make(),
$this->getHeaderComponent(),
Content::make([
Components::make($this->getPage()->getComponents()),
]),
$this->getFooterComponent(),
])->class('layout-page'),
]),
])->class('theme-minimalistic'),
])
->customAttributes(['lang' => $this->getHeadLang()])
->withAlpineJs()
->withThemes(),
]);
}
If using both Sidebar and TopBar, TopBar must come first in the Wrapper.
See references/layouts.md for the full layout API.
The menu is declared in the layout's menu() method:
use MoonShine\MenuManager\MenuItem;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuDivider;
protected function menu(): array
{
return [
MenuGroup::make('Content', [
MenuItem::make('Articles', ArticleResource::class, 'document-text'),
MenuItem::make('Categories', CategoryResource::class, 'tag'),
])->icon('newspaper'),
MenuDivider::make(),
MenuItem::make('Dashboard', DashboardPage::class, 'home'),
MenuItem::make('External', 'https://example.com', blank: true),
];
}
->badge(fn() => Comment::count())->canSee(fn() => auth()->user()->isAdmin())->translatable('menu')Replace manual menu declaration with automatic discovery:
protected function menu(): array
{
return $this->autoloadMenu();
}
Control autoload behavior with attributes on resources/pages:
use MoonShine\MenuManager\Attributes\SkipMenu;
use MoonShine\MenuManager\Attributes\Group;
use MoonShine\MenuManager\Attributes\Order;
use MoonShine\MenuManager\Attributes\CanSee;
#[SkipMenu]
class ProfilePage extends Page {}
#[Group('Content', 'newspaper', translatable: true)]
#[Order(1)]
class ArticleResource extends ModelResource {}
#[CanSee(method: 'canViewInMenu')]
class SecretResource extends ModelResource
{
public function canViewInMenu(): bool
{
return auth()->user()->isAdmin();
}
}
See references/menu-system.md for the full menu API.
Override colors in the layout's colors() method:
use MoonShine\Contracts\ColorManager\ColorManagerContract;
protected function colors(ColorManagerContract $colorManager): void
{
$colorManager
->primary('#1E96FC')
->secondary('#1D8A99')
->body('249, 250, 251')
->dark('30, 31, 67', 'DEFAULT')
->dark('55, 65, 81', 700)
->dark('31, 41, 55', 800)
->dark('17, 24, 39', 900)
->successBg('209, 255, 209')
->successText('15, 99, 15')
->errorBg('255, 224, 224')
->errorText('81, 20, 20');
// Dark theme overrides
$colorManager
->body('27, 37, 59', dark: true)
->dark('39, 45, 69', 700, dark: true)
->dark('27, 37, 59', 800, dark: true)
->dark('15, 23, 42', 900, dark: true);
}
public function boot(ColorManagerContract $colors): void
{
$colors->primary('#7843e9');
}
Layout
colors()loads after ServiceProvider and takes precedence.
$colorManager->background('27, 37, 59'); // body + dark.800 + dark body
$colorManager->content('39, 45, 69'); // dark.700 + dark.900
$colorManager->tableRow('40, 51, 78'); // dark.600
$colorManager->borders('53, 69, 103'); // dark.300
$colorManager->dropdowns('48, 61, 93'); // dark.400
$colorManager->buttons('83, 103, 132'); // dark.50 + dark.500 + dark.400
$colorManager->dividers('74, 90, 121'); // dark.100 + dark.200
See references/colors.md, references/icons.md, and references/assets-branding.md for the full color, icon, and asset API.
php artisan moonshine:page CustomPage
namespace App\MoonShine\Pages;
use MoonShine\Laravel\Pages\Page;
use MoonShine\UI\Components\Layout\Box;
use MoonShine\UI\Components\Layout\Grid;
use MoonShine\UI\Components\Layout\Column;
class CustomPage extends Page
{
protected string $title = 'Dashboard';
protected string $subtitle = 'Overview';
protected function components(): iterable
{
return [
Grid::make([
Column::make([
Box::make([/* ... */])
])->columnSpan(6),
Column::make([
Box::make([/* ... */])
])->columnSpan(6),
])
];
}
}
class CustomPage extends Page
{
protected ?string $layout = MyLayout::class;
}
// Or via attribute
use MoonShine\Core\Attributes\Layout;
#[Layout(MyLayout::class)]
class CustomPage extends Page {}
use MoonShine\Contracts\UI\LayoutContract;
protected function modifyLayout(LayoutContract $layout): LayoutContract
{
return $layout->title('Custom Title')->description('Custom description');
}
onLoad() -- runs when the page is the active route (add assets, authorize, etc.)booted() -- runs when MoonShine creates the page instance (early initialization)final class MoonShineLayout extends AppLayout
{
protected function isAlwaysDark(): bool
{
return true;
}
}
The ThemeSwitcher component is included by default in getSidebarComponent() and getTopBarComponent(). It toggles the .dark class on the root <html> element.
Sidebar, TopBar, and MobileBar are styled with dark colors by default. If you add custom components to them, force dark mode with:
$this->getSidebarComponent()->class('dark'),
$this->getTopBarComponent()->class('dark'),
Add custom CSS/JS to a layout:
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;
use MoonShine\AssetManager\InlineCss;
protected function assets(): array
{
return [
...parent::assets(),
Css::make('/css/custom.css'),
Js::make('/js/custom.js')->defer(),
InlineCss::make(':root { --radius: 0.15rem; }'),
];
}
use Illuminate\Support\Facades\Vite;
use MoonShine\AssetManager\Js;
protected function assets(): array
{
return [
Js::make(Vite::asset('resources/js/app.js')),
];
}
protected function getLogo(bool $small = false): string
{
return $small ? '/images/logo-small.png' : '/images/logo.png';
}
Or via config:
// config/moonshine.php
'logo' => '/images/logo.png',
'logo_small' => '/images/logo-small.png',
protected function getFaviconComponent(): Favicon
{
return parent::getFaviconComponent()->customAssets([
'apple-touch' => '/favicon/apple-touch-icon.png',
'32' => '/favicon/favicon-32x32.png',
'16' => '/favicon/favicon-16x16.png',
'safari-pinned-tab' => '/favicon/safari-pinned-tab.svg',
'web-manifest' => '/favicon/site.webmanifest',
]);
}
protected function getFooterMenu(): array
{
return ['https://docs.example.com' => 'Docs'];
}
protected function getFooterCopyright(): string
{
return sprintf('© %d My Company', now()->year);
}
Layouts can also be written in pure Blade using <x-moonshine::layout.*> components. Key components: layout, layout.html, layout.head, layout.body, layout.wrapper, layout.sidebar, layout.header, layout.content, layout.menu, layout.logo, layout.theme-switcher, layout.burger, layout.assets, layout.favicon.
See references/layouts.md for the full Blade component reference.