cboxdk / laravel-console-kit
Extension hooks for a Cbox admin console — nav areas, feature gates, UI slots, dashboard cards and per-tenant branding that an optional package registers into via composer, with zero host edits. The plugin pattern behind billing and other drop-in modules.
Requires
- php: ^8.4
- illuminate/contracts: ^12.0 || ^13.0
- illuminate/support: ^12.0 || ^13.0
- illuminate/view: ^12.0 || ^13.0
Requires (Dev)
- inertiajs/inertia-laravel: ^2.0 || ^3.0
- larastan/larastan: ^3.0
- laravel/pint: ^1.18
- orchestra/testbench: ^10.0 || ^11.0
- pestphp/pest: ^3.5 || ^4.0
Suggests
- inertiajs/inertia-laravel: Shares the `shell` prop lazily with every Inertia page (without it, HandleShell shares it with Blade views).
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-11 19:03:07 UTC
README
cboxdk/laravel-console-kit — the extension hooks a Cbox admin console exposes so an
optional package can composer require in and light up a whole feature — nav, UI and
gates — with zero edits to the host app. It's the plug socket; a feature package
(billing, and others) is the plug.
The same kit is adopted by every console (cbox-id, ai-assistant, cortex, …), so one plugin works across all of them.
The four hooks
use Cbox\Console\Kit\Facades\Console; // 1. Nav — add an area, or add pages to a host area. Gate a page on a feature. Console::nav()->area('billing', 'Billing', 'card', order: 90) ->page('billing.plan', 'Plan', feature: 'billing') ->page('billing.invoices', 'Invoices', feature: 'billing'); // 2. Features — deny-by-default; a live resolver decides if it's on. Console::features()->register('billing', fn () => app()->bound(BillingManagement::class)); // 3. Slots — inject content into an EXISTING page. Console::slots()->add('settings.sections', 'billing::settings-card'); // 4. Dashboard cards — sugar over the well-known dashboard slot. Console::dashboardCard('billing::plan-card', order: 10);
Host side
Adopt the kit in your console shell — seed your defaults, render the registry:
{{-- nav --}} @foreach (\Cbox\Console\Kit\Facades\Console::nav()->areas() as $area) {{-- render $area->label / $area->icon; for each $area->pages() show it unless $page->feature and ! Console::featureActive($page->feature) --}} @endforeach {{-- slots --}} @consoleSlot('console.dashboard.cards') @consoleSlot('settings.sections')
Gate a plugin's routes so they don't even exist when its feature is off:
Route::middleware('console.feature:billing')->group(fn () => /* billing routes */);
The shared shell
The kit also builds the shell prop every Cbox app renders with cbox-ui: the rail, the
header's context selectors, the ⌘K palette, Help, the bell and the app switcher.
Console::shell() ->app('infra', 'Cbox Infra') ->levels(app(OrganizationLevel::class), new ProjectLevel, new EnvironmentLevel) ->search(new DeploymentSearch) ->actions(fn () => [PaletteAction::route('deployments.create', 'New deployment')]) ->helpTopic(fn (Request $r) => $r->route()?->getName()); // routes/web.php Console::shellRoutes(); Route::middleware(['web', 'auth', 'console.shell'])->group(/* your pages */);
Everything is built from the app's own data; nothing waits on another service. See the quickstart and the shared shell.
Why a separate package
The hook contracts must be reusable across consoles, so they can't live inside any one app or inside the billing plugin. This package is just the shared socket — no feature logic, no UI of its own. Deny-by-default throughout: an unregistered feature is off, a gated page is hidden, a guarded route 404s.
License
MIT © Cbox.