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

App Laravel Package

moonshine/app

Core application package for MoonShine, the Laravel admin panel, providing the foundation for building admin interfaces with resources, CRUD screens, forms, filters, and extensible components that integrate smoothly with Laravel.

View on GitHub
Deep Wiki
Context7

Getting Started

Install (fresh Laravel 11/12 app)

composer require moonshine/moonshine
php artisan moonshine:install
php artisan moonshine:user      # create the first admin

Then log in at /admin with the credentials you just created. Everything below assumes that flow worked — if /admin 404s, the service provider isn't registered (see Gotchas).

Where to look first

  1. config/moonshine.php — auth guard, route prefix, middlewares, layout/theme, cache settings.
  2. The generated MoonShineServiceProvider (registered in bootstrap/providers.php) — this is where resources are registered via $core->resources([...]) and where the menu is built via $core->menu(...) / MenuManager.
  3. app/Moonshine/Resources/ — the generated MoonShineUserResource is your reference implementation; copy its structure rather than reading docs cold.
  4. vendor/moonshine/moonshine/src/UI/Fields/ — the canonical list of available field types.

First use case: one resource, end to end

php artisan moonshine:resource Post

Edit app/Moonshine/Resources/PostResource.php: set protected string $model = Post::class;, fill fields() with ID::make()->sortable(), Text::make('Title'), Textarea::make('Body'), BelongsTo::make('Author', 'author', resource: UserResource::class) — and make sure it's registered in the service provider. Menu entry, index listing, create/edit form, detail page, and delete all exist at that point. That single resource is the fastest way to learn the framework's shape; everything else is a variation on it.

Implementation Patterns

Resource as the unit of work. A ModelResource is the join point for fields(), pages() (Index/Form/Detail), filters(), search(), $with (eager loading), and $sortable. Prefer overriding the resource over writing custom controllers — you rarely need a controller at all.

Field sets and reuse. Extract field arrays to traits or static builders when the same model appears in multiple resources or in a nested relationship. Keep field names identical to the model attribute or accessor name; Moonshine maps them positionally on save, so a mismatch fails silently as "field not saved" rather than throwing.

Conditional UI instead of conditional logic. ->canSee(fn() => user()->isSuperUser()) on fields, menu items, and action buttons is the idiomatic way to gate features. Pair it with Laravel policies on the underlying model for defense in depth — canSee is UI-only and does not protect the endpoint.

Actions. ActionButton::make('Publish')->method('publish') on Detail/Index pages, with the method living on the resource or page. Bulk actions on IndexPage for anything that loops — one request beats N. For anything longer than a second or two, dispatch a job from the action method and return a toast, rather than blocking the admin request.

Filters. Declare on IndexPage::filters(), and drop to QueryTag (or an explicit closure) the moment the filter needs a whereHas or a date range on a joined column. Custom filters are a supported extension point, not a hack.

Custom pages and components. Extend Page/CrudPage, define components(), and register the page alongside resources. Custom components extend Component and render a Blade view — this is the clean way to embed charts, dashboards, or third-party widgets without fighting the default layout.

Menu as configuration, not code paths. Build with Menu::make([...]), MenuGroup, and canSee closures. Because the menu is registered in the service provider, it caches well but does not hot-reload in production — see below.

Auth. Moonshine ships its own moonshine guard and moonshine_users table, separate from your app's users. In tests, use $this->actingAs($admin, 'moonshine'); in application code, auth('moonshine')->user() — auth()->user() will return the wrong user or null and cause confusing null-pointer failures inside field closures.

Deployment. Treat the admin panel like any other frontend asset: publish/build whatever theme customization you added, run php artisan optimize (config + route + view cache), and confirm the asset step ran in CI. Missing assets present as an unstyled but otherwise functional panel, which is easy to miss in a smoke test.

Gotchas and Tips

  • Guard mismatch is the #1 self-inflicted bug. Everything user-dependent inside fields, actions, and menu closures must go through the moonshine guard. Null users inside canSee usually mean this, not a broken login.
  • Separate user tables. Do not point the Moonshine guard at your users table expecting single sign-on; either seed admins into moonshine_users or write a deliberate custom guard/provider. Half-migrating this later is painful.
  • Silent field failures. A field with a name that doesn't match the attribute, or a type the model cast doesn't support (raw string into a datetime column, array into a non-JSON column), often saves nothing and reports nothing. When a field "doesn't persist," check the name and the cast first.
  • N+1 on index pages. The resource's indexQuery/$with is your lever. BelongsTo columns on the index are the usual culprit; a listing that takes 3s locally will time out in production.
  • Registration is cached. Adding a resource or menu item requires clearing compiled/cached config in production. If a new resource exists locally but not on the server, this is why.
  • Asset/theme drift. Custom Tailwind/Blade overrides live outside the vendor tree but depend on it. After any upgrade, rebuild and eyeball the panel — this is the most likely place a minor release bites you.
  • Version pinning. The 4.1.0 release notes are just a changelog link, so there's nothing in the notes to reason about. It's a minor bump under semver and no breaking changes are advertised, so it should be a drop-in — but pin "moonshine/moonshine": "~4.0" (or a specific 4.0.x) until you've read the compare diff, run your test suite against a staging copy, and clicked through your most customized resource and one custom page. Watch specifically for internal Blade view or CSS class changes affecting any theme overrides you carry.
  • Extension points worth knowing early: custom Field subclasses (for a repeated input pattern), custom Component + Blade view, custom Page, custom filter classes, and the service provider itself for cross-cutting registration. Almost every "I need to hack the layout" instinct is better served by a custom component.
  • Debugging: when behavior diverges from docs, read the vendor source for that field/component — Moonshine's source is compact and the docs sometimes lag minor releases. ->canSee(false) and dd() inside a field closure remain the fastest way to isolate whether the problem is registration, authorization, or rendering.
  • Testing: route-level feature tests (actingAs on the moonshine guard, hit the resource index, assert assertOk and a known column) catch the majority of upgrade breakage cheaply. Add one before you upgrade to 4.1.0 if you don't have one.
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