conedevelopment/root
A Laravel package by Cone Development that provides foundational utilities and conventions to streamline application development. Root helps organize code and reduce boilerplate, offering a lightweight base for building and extending Laravel projects.
Install and publish. Require the package and publish its config/assets, then confirm what the service provider registers:
composer require conedevelopment/root
php artisan vendor:publish --provider="ConeDevelopment\Root\RootServiceProvider"
php artisan migrate
Because the package is small and moves quickly, treat the published config/root.php and the package's routes/ directory as the source of truth rather than the README. The config typically controls the route prefix, middleware stack, and auth guard — set those before you build anything else.
Where to look first, in order:
config/root.php — route prefix, middleware, guard, and any navigation/branding options./root, /admin, etc.), the controller namespaces, and which middleware actually runs.src/Resources/ (or equivalent) — the base resource/field classes you will extend. Skim the base class to see which methods are abstract vs. overridable.First use case: one resource, end to end. Pick a model you already have (e.g. Post), create a resource class that declares its fields and table columns, register it with the package (usually a Root::resources([...]) call in a service provider or a root.php array), then hit the admin URL as an authenticated user. Get list → create → edit → delete working before adding filters, actions, or custom fields. That single vertical slice exposes almost every integration point you'll need later: guard, policy, field binding, validation, and asset pipeline.
One resource per model, thin by default. Keep resource classes declarative — fields, columns, filters, and validation rules only. Push query scoping into model scopes or a dedicated query class, and push mutation logic into actions/services. Resources are hard to unit test and easy to bloat; anything with a branch belongs outside.
Authorization via policies, not resource-level checks. The package will almost certainly consult Laravel's gate/policy system for viewAny, view, create, update, delete. Register policies the normal way and let the admin inherit them. This keeps the admin panel consistent with your API/UI permissions and avoids a second permission system to maintain. If the package ships its own permission layer, wrap it in a thin adapter so you can swap it later.
Custom fields as first-class extensions. When a built-in field doesn't fit, extend the package's base field class rather than hacking a Blade view. A custom field is usually: a PHP class declaring the column/component name and any props, plus a view. Register it once (container binding or config array) and reuse it across resources. This is the cleanest extension point and the one least likely to break on upgrade.
Actions over controller overrides. For "publish", "impersonate", "export" style buttons, use the package's action/bulk-action mechanism if it has one. Overriding controllers ties you to internal method signatures; actions are a documented surface.
Multi-guard and multi-panel setups. If the app already has a web guard for end users, give the admin its own guard and provider rather than sharing. Set the guard in config, and remember that the package's middleware, the session cookie, and your policy checks all need to agree on which guard is active. For a second panel (e.g. a support console), prefer a second route group with its own middleware over duplicating resources.
Testing. Write feature tests that actingAs($admin) and assert on the admin routes: index renders, create persists, validation fails, unauthorized user gets 403. These catch 90% of upgrade breakage and cost little. Use RefreshDatabase and factories you already have.
public/vendor/... goes stale silently — the panel will "work" but look broken or miss new field styles. Add vendor:publish --tag=root-assets --force to your deploy notes.config/root.php or resource registration, run php artisan config:clear and route:clear locally. In production, resource registration that happens in a service provider is fine, but anything reading the filesystem at boot will break under config:cache.admin and you already have an admin route group, one silently shadows the other. Check with php artisan route:list | grep root (or your prefix) after install and after adding resources.config/auth.php guards, the package's guard setting, and the auth middleware alias all point at the same guard. Session domain/cookie name mismatches produce the same symptom on subdomains.with() / withCount() on the resource or its base query, and check the query log on a seeded table before shipping.php artisan storage:link plus a correctly configured disk; if uploads "succeed" but 404, it's almost always the symlink or the disk's url setting, not the field.route:list for the actual URL/middleware, Log::info inside a resource's query callback, Laravel Telescope for the SQL and gate checks, and browser devtools for asset 404s. If it's Inertia/Vue-based, the Vue devtools network tab shows the page props the resource produced — that's your fastest window into what the PHP side actually sent.docs/admin.md describing how resources, policies, and custom fields are wired in your app — not a link to the package README.How can I help you explore Laravel packages today?