Account Integration
v1.4
Modules can inject pages into the customer account area (the sidebar that shows Downloads, Orders, Subscriptions, etc.) without touching any core view file.
Registering an account menu item
Call registerAccountMenuItem() in your module's boot():
$this->registerAccountMenuItem(
label: 'My Feature',
route: 'my-plugin.account.index',
icon: 'extension', // Material Symbols icon name
order: 30,
routes: ['my-plugin.account.*'],
);| Parameter | Type | Default | Description |
|---|---|---|---|
label | string | — | Text shown in the sidebar |
route | string | — | Named route for the link |
icon | string | 'extension' | Material Symbols icon name |
order | int | 50 | Sort position. Lower = higher up in the list |
routes | array | [$route] | Route name patterns used for active-state highlight. Supports wildcards: my-plugin.account.* |
condition | callable|null | null | Optional. Called at render time — return false to hide the item (see below) |
Conditional visibility
Use condition to show or hide the item based on runtime state — for example, only show it to users who have a specific subscription or role:
$this->registerAccountMenuItem(
label: 'API Keys',
route: 'my-plugin.account.index',
icon: 'key',
order: 30,
routes: ['my-plugin.account.*'],
condition: function () {
if (! auth()->check()) {
return false;
}
// Only show to users with an active subscription
return \App\Models\Subscription::where('user_id', auth()->id())
->where('status', getConstant('SUBSCRIPTION_STATUS_ACTIVE'))
->exists();
},
);The condition callable is evaluated once per page render. If it returns false, the link is not rendered — the user never sees it and receives a 404 if they try to visit the URL directly (assuming your routes also apply the appropriate middleware).
Building account pages
Account pages live inside your module. Extend the platform layout and include the account nav partial to get the full sidebar automatically:
{{-- modules/MyPlugin/resources/views/account/index.blade.php --}}
@extends('theme::layouts.app', ['title' => 'My Feature'])
@section('content')
<main class="flex-grow w-full max-w-[1440px] mx-auto px-6 lg:px-10 py-10">
<div class="flex flex-col lg:flex-row gap-10">
<aside class="w-full lg:w-64 flex-shrink-0">
@include('theme::partials.account.nav')
</aside>
<section class="flex-grow">
<h1 class="text-2xl font-bold text-text-main dark:text-white mb-6">My Feature</h1>
{{-- your content here --}}
</section>
</div>
</main>
@endsectionIncluding theme::partials.account.nav automatically renders your injected sidebar link — no extra work needed.
Routes
Register account routes in routes/web.php:
Route::prefix('account/my-plugin')
->middleware(['web', 'auth'])
->name('my-plugin.account.')
->group(function () {
Route::get('/', [MyPluginAccountController::class, 'index'])->name('index');
Route::post('/', [MyPluginAccountController::class, 'store'])->name('store');
Route::delete('/{id}', [MyPluginAccountController::class, 'destroy'])->name('destroy');
});Use
account/as your URL prefix to keep customer-facing pages consistent with the rest of the account area.
Protecting pages with saas.auth (optional)
If your module's account pages should only be accessible to users with an active SaaS subscription, apply the saas.auth middleware (provided by the Saas module):
Route::prefix('account/my-plugin')
->middleware(['web', 'auth', 'saas.auth'])
->name('my-plugin.account.')
->group(...);saas.auth will:
- Redirect non-subscribers to the pricing page.
- Inject the resolved
SubscriptionandPricingTierinto the request:
public function index(Request $request)
{
$subscription = $request->attributes->get('saas_subscription');
$tier = $request->attributes->get('saas_tier');
}Dependency note:
saas.authis registered by the Saas module. If the Saas module is not active, this middleware alias won't exist. Only use it if your module explicitly depends on the Saas module.
Replacing the account nav entirely
Use registerAccountNavOverride() when your module needs a completely different sidebar — for example, when running in a dedicated SaaS mode where the standard Downloads / Orders / Subscriptions links make no sense.
$this->registerAccountNavOverride(
'my-plugin::partials.account.nav', // view to render instead of the core nav
fn () => setting('my_plugin.saas_mode'), // optional condition; always applies when null
);The first registered override whose condition returns true is used. When the override is active, theme::partials.account.nav renders your view instead of the standard sidebar.
Hiding core account nav items
Use registerHiddenNavItems() to selectively suppress specific core links without replacing the entire nav:
$this->registerHiddenNavItems(
['downloads', 'orders', 'licenses'],
fn () => setting('my_plugin.saas_mode'),
);Supported slugs:
| Slug | Nav item hidden |
|---|---|
downloads | Downloads |
orders | Orders |
subscriptions | Subscriptions |
licenses | Licenses |
reviews | Reviews |
support | Support |
account | Account (profile/settings) |
The condition callable is evaluated at render time. Pass null as the second argument to hide items unconditionally.
Custom UI instead of the account layout
If you want a fully branded custom UI rather than the standard account area look, ship your own layout and don't include the account nav:
@extends('my-plugin::layouts.app')
@section('content')
{{-- completely custom UI --}}
@endsectionBoth approaches are valid — the module system imposes no constraints on how your pages look.