mpociot/cockpit
Cockpit is a Laravel package for quickly adding an admin cockpit to your application. It gives you a foundation for managing resources, organizing backend tools, and building custom dashboard interfaces without starting from scratch.
Positioning. Cockpit is a config-driven CRUD scaffold for internal Laravel back-offices: declare an Eloquent model and its fields once, and the package emits list/create/edit/delete screens over a Vue SPA and a JSON API. As a TPM artifact, treat it as a prototype-grade accelerator rather than a platform component. The signal is unambiguous — 39 stars, zero dependents, evaluation score 0.255 — so nothing in the ecosystem is exercising this code against a current Laravel/PHP pair. The product question is therefore not "is this good?" but "is a scoped spike cheaper than the alternative, and can we delete it in two days if not?"
Architecture fit. Fit is conditional on three properties your application must already have:
| Requirement | Why it matters | TPM verification |
|---|---|---|
| Existing auth guards + policies | Cockpit reuses Laravel guards/middleware but resource visibility is often config-driven | Read the service provider; confirm Gate/can: can gate every panel route |
| Model-centric domain | Value comes from resource-per-model; screens are views over models | Count how many of the target admin screens map cleanly to one model |
| A place to host config | Resource definitions are presentation config, not business logic | Ensure a single owned directory (app/Cockpit/) exists in the plan |
Where the back-office is genuinely just "browse, search, edit a handful of tables for trusted operators," fit is decent. Where the panel needs per-tenant isolation, SSO, granular roles, or an auditable authorization model, fit is poor and this should not pass intake.
Integration feasibility. Mechanically straightforward for one engineer: composer require, vendor:publish, read the (small) service provider, register one low-risk model, verify a listing and an edit form render behind your own guard. That is a one-to-two-day vertical slice and it validates the entire premise — config discovery, field rendering, persistence, and auth. Two real friction points: (1) composer.json version constraints may top out below your framework, in which case pinning/backporting costs more than writing the screens; (2) generated forms are a UI over validation, not validation itself, so every writable field needs a FormRequest or model-level rule or you have effectively shipped an unvalidated write endpoint.
Technical risk. Ranked, with the mitigation each implies:
can: yourself.updated_at checks in your save path if records matter, or accept the risk in writing.COUNT(*) on every request, and N+1 on relation columns in listing views. Verify pagination, index search columns, eager-load relations.Key questions to resolve before commitment.
composer why-not mpociot/cockpit say against our locked framework version — supported, pinnable, or dead on arrival?Stack fit. Cockpit assumes Laravel with a Vue front-end and a JSON API, registered via a service provider, configured via publishable config and views. It slots alongside an existing app rather than replacing anything — no schema ownership, no migration of core tables, no separate runtime. That keeps blast radius small. The one architectural decision it forces is where resource definitions live: if they are PHP config files, config:cache freezes them and a deploy that adds a panel without a config clear ships a dashboard missing a section; if they are service-provider registrations, they are cache-safe but you forgo config caching benefits. Pick one and write it into the deploy runbook — this is a runbook decision, not a code decision, and it should be made at kickoff rather than discovered in production.
Compatibility. Do not trust the README; trust the lockfile. First action in throwaway branch:
composer require mpociot/cockpit --dry-run
composer why-not mpociot/cockpit
Then read vendor/mpociot/cockpit/src/'s service provider top to bottom — it is small and is the authoritative spec for routes, middleware, view namespaces, and config keys, since docs likely lag current behavior. Run vendor:publish interactively and record every tag offered (config, views, assets, possibly migrations); the documented set will not match. Pin the exact version, commit the lockfile, and commit any compiled published assets rather than building at deploy time — determinism over freshness.
Migration path (in, then out). Inbound is additive and low-risk:
route:list --path=admin, inspect the middleware column on every generated route.Route::middleware(['web', 'auth:admin'])->prefix('admin')->group(base_path('routes/cockpit.php'));
Outbound must be designed before inbound. Keep definitions in one directory, register resources/widgets/navigation from your own App\Providers\CockpitServiceProvider rather than editing vendor, and never fork Blade for logic — views are for branding only. If that discipline holds, removal is rm -rf app/Cockpit plus one provider line.
Sequencing. Four gates, each with a stop condition:
| Phase | Duration | Deliverable | Stop if |
|---|---|---|---|
| 0. Compatibility probe | 0.5 day | why-not output, provider read, publish tags logged |
Constraints exclude our framework |
| 1. Vertical slice | 1–2 days | One model, list + search + edit, behind own guard, two auth tests green | Auth cannot be Gate-driven |
| 2. Hardening | 2–3 days | CI route assertion, validation on every writable field, observer-based audit trail, pagination + index check | Perf or audit needs exceed patch scope |
| 3. Scope decision | 0.5 day | Named fork owner, capacity line item, exit drill performed | No owner available |
Two tests carry most of the insurance and should exist by end of Phase 1: anonymous users redirect away from the panel, and an authorized operator gets a 200. Run both across every panel route via a data provider. Execute an exit drill before Phase 3 sign-off — delete the directory, remove the provider line, confirm the app still boots. A two-day deletion that has never been rehearsed is a quarter-long rewrite waiting to happen.
Maintenance. You are the maintainer. There is no upstream cadence to plan around, so the honest line item is fork ownership, not dependency management: roughly 10–20% of one engineer ongoing, plus a concentrated pass at every Laravel major. Pin exactly, commit the lockfile, and treat any needed extension point that doesn't exist as a 5–10 line fork change — which is precisely the burden the star count implied at intake. Put the owner's name in the plan; "the platform team" will not pick this up.
Support. Support model is internal-only and tier-1 by the owning engineer. No vendor, no community, no CVE feed. Compensate with process: audit-trail via a LogsAdminChanges observer attached to each model the panel touches (keep it in your code so it survives migration off Cockpit), a documented deploy runbook covering the config-cache-vs-provider decision, and a standing rule that "quick admin screen" does not become the default answer — write down the criteria for what earns a Cockpit screen versus a real feature before the third panel.
Scaling. Admin panels are low-QPS; the risk is per-request cost, not throughput. Three known ceilings: unbounded listing screens (confirm pagination is actually on and COUNT(*) isn't running per request), search boxes hitting unindexed columns (operators will paste wildcards and trigger a sequential scan), and N+1 on relation columns rendering $row->owner->name per row. Widgets deserve specific scrutiny — a dashboard card doing three unindexed latest()->take(5) queries against a 5M-row table is a page that times out at 9am Monday. Index the search and sort columns in the spike, not after the first complaint.
Failure modes. With detection and response owned up front:
| Failure mode | Signature | Detection | Response |
|---|---|---|---|
| Route outside middleware group | Panel reachable without guard | CI assertion enumerating admin routes + guard/gate; route:list --path=admin diffed after every composer update |
Block deploy; patch registration order |
| Config-cache staleness | Deploy ships panel missing a new section | Post-deploy smoke test hitting each panel route | config:clear + redeploy; fix runbook |
| Concurrent edit clobber | Silent last-write-wins | No signal — silent by design | updated_at check in save path, or documented risk acceptance |
| Blank render / 404 after publish | Stale compiled Blade | view:clear, then check view namespace matches published views |
Standard debugging checklist in runbook |
| Performance regression on lists | Slow first query, escalating | Slow-query log / Telescope | Pagination, index, eager-load override |
Ramp-up. Deliberately cheap, and that is the package's main operational virtue: the codebase is small enough to read as a spec in an afternoon, and the provider read is the highest-value hour of onboarding. Plan roughly one engineer-day to first working slice, three to five days to a hardened one, and a half-day for the exit drill. The real ramp-up cost is not learning Cockpit — it is the organizational work of naming an owner, budgeting the 10–20%, and agreeing in writing that this is a scoped, deletable prototype rather than a foundation. If that agreement can't be reached, the correct decision is to skip it and build thin on Laravel primitives or adopt a maintained alternative like Filament or Nova.
How can I help you explore Laravel packages today?