Skip to main content
The layout is the persistent application shell — the sidebar, header, and any chrome that wraps every page. Core ships three layout types that you extend and register in config.

Layout Types

AppLayout

AppLayout extends CoreAppLayout and is the full application shell with a sidebar, settings navigation, and secondary footer links. Override navigation() to define the sidebar structure.
app/Layouts/AppLayout.php
<?php

namespace App\Layouts;

use Inly\Core\Layouts\CoreAppLayout;
use Inly\Core\Layouts\NavigationItem;
use Inly\Core\Layouts\NavigationSection;

class AppLayout extends CoreAppLayout
{
    protected function navigation(): void
    {
        $this->navMain([
            NavigationSection::make(__('Sales'), [
                NavigationItem::make('deals.index', __('Deals'))->icon('Handshake'),
                NavigationItem::make('contacts.index', __('Contacts'))->icon('Users'),
            ])->icon('TrendingUp')->color(220),
        ]);

        $this->navSettings([
            NavigationItem::make('integrations.index', __('Integrations'))
                ->icon('GlobeLock')
                ->hidden(fn () => ! user()->can(Permission::MANAGE_SYSTEM->value)),
        ]);
    }
}

PortalLayout

PortalLayout extends CorePortalLayout, a simplified layout for customer-facing portal pages. It only supports navMain().
app/Layouts/PortalLayout.php
<?php

namespace App\Layouts;

use Inly\Core\Layouts\CorePortalLayout;
use Inly\Core\Layouts\NavigationItem;

class PortalLayout extends CorePortalLayout
{
    protected function navigation(): void
    {
        $this->navMain([
            NavigationItem::make('portal.dashboard', __('Dashboard'))->icon('LayoutDashboard'),
        ]);
    }
}

GuestLayout

Used for unauthenticated pages (login, password reset, etc.). It has no navigation and requires no configuration — use CoreGuestLayout directly without extending it.

Registration

Register your layout classes in config/core.php:
config/core.php
'layouts' => [
    'app'    => App\Layouts\AppLayout::class,
    'portal' => App\Layouts\PortalLayout::class,
    'guest'  => Inly\Core\Layouts\CoreGuestLayout::class,
],
Each page class resolves its layout from this config — AppPage uses core.layouts.app, PortalPage uses core.layouts.portal, and GuestPage uses core.layouts.guest.

Overriding the Layout Per Page

To use a different layout on a specific page, call ->layout() on the page object:
return CoreShowPage::make('portal/portal-show')
    ->layout(PortalLayout::class)
    ->title(__('Portal'));

Define navigation inside navigation() using the methods below. For the full NavigationItem, NavigationSection, and NavigationSecondaryItem API — icons, badges, conditional visibility, sub-items — see Navigation. Populates the primary sidebar. Accepts NavigationItem and NavigationSection objects.
$this->navMain([
    NavigationItem::make('dashboard', __('Dashboard'))->icon('LayoutDashboard'),
    NavigationSection::make(__('Sales'), [
        NavigationItem::make('deals.index', __('Deals'))->icon('Handshake'),
    ])->icon('TrendingUp')->color(220),
]);
Injects items into the built-in Settings accordion at the bottom of the main navigation. Core automatically adds system items (users, workflows, developer) alongside yours.
$this->navSettings([
    NavigationItem::make('integrations.index', __('Integrations'))->icon('Plug'),
]);
Adds external links to the sidebar footer.
use Inly\Core\Layouts\NavigationSecondaryItem;

$this->navSecondary([
    NavigationSecondaryItem::make(__('Documentation'), 'https://docs.example.com')
        ->icon('BookOpen'),
    NavigationSecondaryItem::make(__('Support'), 'https://support.example.com')
        ->icon('LifeBuoy'),
]);
Adds links to the Inly customer portal in the sidebar footer. Links are gated behind CorePermission::VIEW_INLY_USER_GUIDE and CorePermission::VIEW_INLY_PROJECT_OVERVIEW.
$this->setInlyLinks(
    userGuideUrl: 'https://docs.example.com/user-guide',
    projectOverviewUrl: 'https://portal.example.com/project'
);
setInlyLinks() and navSecondary() are only available on CoreAppLayout. CorePortalLayout only supports navMain().

Active State Matching

Navigation items use group-based active matching. An item is highlighted when the current route name starts with the same prefix as the item’s route.
  • customers.index is active on customers.index, customers.show, customers.create, etc.
  • Parent items are highlighted when any child route is active.
  • When a sub-item is active, only the sub-item is highlighted — not the parent.
Current routeHighlighted item
customers.show”Customers”
customers.show.invoices”Invoices” sub-item only