konekt/appshell
Konekt AppShell is a modular Laravel application shell for building admin panels and business apps. It bundles authentication, permissions, settings, menus, widgets, localization, and a customizable UI foundation to speed up development.
AppShell is the "glue" layer of the Konekt ecosystem: it wires together konekt/concordat (model contracts), konekt/acl (roles/permissions), konekt/address, konekt/customer, and a Blade-based admin UI into a single foundation you build a business app on top of. Treat it as a starting skeleton, not a drop-in admin panel.
Minimal setup:
composer require konekt/appshell
php artisan vendor:publish --provider="Konekt\AppShell\Providers\AppShellServiceProvider"
php artisan migrate
Then:
config/appshell.php (and the package's src/Providers/AppShellServiceProvider.php on GitHub) to understand what it registers: routes, view namespaces, Blade components, menu/breadcrumb registries, and model bindings.config/concordat.php / the Concordat registrations — AppShell resolves users, customers, and addresses through contracts, so the models it uses are configurable and swappable.Admin user type distinct from frontend Customer users) and log in to the /admin area to confirm the shell boots.First meaningful use case: scaffold a backend admin area with a dashboard, a menu, a resource list/detail screen, and ACL-gated actions — then extend it with your own domain CRUD. The quickest win is to get one custom model rendered via the AppShell table/form helpers so you learn the conventions before scaling.
Two-guard auth by default. AppShell assumes a split between backend users (Admin) and frontend users (Customer/Client). Keep these guards and user types distinct from day one — retrofitting a single-user model onto a two-guard app is painful because ACL, menus, and layouts are scoped to the backend guard.
Extend via contracts, not by editing vendor code. Register your own User, Customer, or Address subclasses in the Concordat/AppShell config and let the package resolve them. This is the supported extension point for adding fields and relationships.
Menu and breadcrumb registries are the primary UI integration surface. Rather than hardcoding nav in Blade, register items through the package's menu API (typically in a dedicated MenuServiceProvider or your AppServiceProvider::boot()), gated by ACL permissions. This keeps navigation consistent and permission-aware.
// illustrative shape — verify against your installed version's API
Menu::addItem('customers', route('appshell.customer.index'))
->permission('list customers');
ACL-gate everything at the route/controller layer, then mirror it in the UI via menu permissions and Blade @can-style checks. Use konekt/acl roles as coarse groupings (admin, operator, viewer) and permissions as the fine-grained unit.
Build resources as list + show + form. AppShell's value compounds when you follow its table/form conventions instead of hand-rolling Bootstrap markup — you get consistent styling, pagination, flash messages, and widget slots for free. Wrap each domain screen in the provided layout and add a breadcrumb trail.
Settings/preferences belong in AppShell's settings layer (backed by config/DB) rather than scattered env() calls, so they're editable from the admin area and cache-friendly.
Integrate with konekt/customer and konekt/address for anything involving accounts and locations — the admin screens, forms, and ACL already know how to talk to those models; fighting them creates duplicate CRUD.
konekt/* versions together and check the package's composer.json against your Laravel version before upgrading — breaking changes ship across the ecosystem, not just this repo.src/ tree and config/ files are the real documentation; bookmark AppShellServiceProvider and the menu/breadcrumb/widget classes.vendor:publish can clobber tweaks.publishes() and any npm/mix expectations.php artisan optimize:clear) before assuming your registration failed.Auth::user() returns null in the backend, confirm the route group uses the backend guard and the user implements the expected Concordat contract.dd() inside your boot() registration and confirm the provider actually runs (check bootstrap/providers.php / config/app.php) and isn't ordered after the consuming view renders.How can I help you explore Laravel packages today?