Layouts
Layouts define the general structure of an HTML page: where the header and footer are, how styles and scripts are included.
Structure of app.blade.php
The main layout is located in views/layouts/app.blade.php. When inheriting from standard, it already exists, but it can be overridden.
Simplified Structure
<!DOCTYPE html>
<html lang="..." data-theme="dark|light">
<head>
<!-- Meta tags, title, description -->
@stack('head')
@stack('styles')
<!-- Include SCSS theme -->
@at(tt('assets/sass/app.scss'))
<!-- HTMX and scripts -->
</head>
<body>
<!-- Header -->
@include('flute::layouts.header')
<!-- Main Content -->
<main id="main">
@stack('content')
</main>
<!-- Footer -->
@include('flute::layouts.footer')
<!-- Modals -->
<div id="modals">
@stack('modals')
</div>
<!-- Scripts -->
@at(tt('assets/scripts/app.js'))
@stack('scripts')
</body>
</html>Overriding Header
Create views/layouts/header.blade.php:
<header class="my-header">
<div class="container">
<div class="header-content">
{{-- Logo --}}
<a href="{{ url('/') }}" class="logo">
<img src="{{ asset(config('app.logo')) }}" alt="{{ config('app.name') }}">
</a>
{{-- Navigation --}}
<nav class="nav">
@foreach (navbar()->all() as $item)
@if (count($item['children']) === 0)
{{-- Regular link --}}
<a href="{{ url($item['url']) }}"
class="nav-link {{ active($item['url']) }}"
@if ($item['new_tab']) target="_blank" @endif>
@if ($item['icon'])
<x-icon :path="$item['icon']" />
@endif
{{ __($item['title']) }}
</a>
@else
{{-- Dropdown --}}
<div class="nav-dropdown">
<button class="nav-link"
data-dropdown-open="nav-{{ $loop->index }}"
data-dropdown-hover="true">
@if ($item['icon'])
<x-icon :path="$item['icon']" />
@endif
{{ __($item['title']) }}
<x-icon path="ph.regular.caret-down" />
</button>
<div data-dropdown="nav-{{ $loop->index }}" class="dropdown">
@foreach ($item['children'] as $child)
<a href="{{ url($child['url']) }}" class="dropdown__item">
@if ($child['icon'])
<x-icon :path="$child['icon']" />
@endif
{{ __($child['title']) }}
</a>
@endforeach
</div>
</div>
@endif
@endforeach
</nav>
{{-- Actions --}}
<div class="header-actions">
{{-- Theme Switcher --}}
<x-header.theme-switcher />
@auth
{{-- Notifications --}}
<x-header.notifications />
{{-- Profile --}}
<x-header.profile />
@else
{{-- Login Button --}}
<x-button href="{{ url('login') }}" size="small">
@t('def.login')
</x-button>
<x-button href="{{ url('register') }}" size="small" type="accent">
@t('def.register')
</x-button>
@endauth
</div>
{{-- Mobile Menu --}}
<button class="mobile-menu-btn" data-trigger-right-sidebar>
<x-icon path="ph.bold.list" />
</button>
</div>
</div>
</header>Styles for Header
// assets/sass/layouts/_header.scss
.my-header {
position: sticky;
top: 0;
z-index: 100;
background: var(--blurred-background);
backdrop-filter: blur(20px);
border-bottom: 1px solid var(--transp-1);
}
.header-content {
display: flex;
align-items: center;
justify-content: space-between;
height: 64px;
gap: var(--space-lg);
}
.logo img {
height: 32px;
width: auto;
}
.nav {
display: flex;
align-items: center;
gap: var(--space-xs);
@include media(mobile) {
display: none;
}
}
.nav-link {
display: flex;
align-items: center;
gap: var(--space-xs);
padding: var(--space-xs) var(--space-sm);
border-radius: var(--border05);
font-size: var(--p);
font-weight: 500;
color: var(--text-muted);
@include transition(all);
&:hover, &.active {
color: var(--text);
background: var(--transp-1);
}
}
.header-actions {
display: flex;
align-items: center;
gap: var(--space-sm);
}
.mobile-menu-btn {
display: none;
@include media(mobile) {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
}
}Overriding Footer
Create views/layouts/footer.blade.php:
<footer class="my-footer">
<div class="container">
<div class="footer-content">
{{-- Logo and description --}}
<div class="footer-brand">
<img src="{{ asset(config('app.logo')) }}" alt="{{ config('app.name') }}">
<p>{{ config('app.description') }}</p>
{{-- Socials --}}
<x-footer.socials />
</div>
{{-- Links from admin panel --}}
<div class="footer-links">
<x-footer.links />
</div>
</div>
<div class="footer-bottom">
<x-footer.copyright />
</div>
</div>
</footer>Stacks (@stack / @push)
Stacks allow you to add content to specific places in the layout.
Available Stacks
| Stack | Where it outputs | Purpose |
|---|---|---|
head | In <head> | Meta tags |
styles | In <head> | CSS files |
scripts | Before </body> | JavaScript |
modals | In #modals | Modal windows |
content | In <main> | Main content |
before-content | Before <main> | Banners |
content-after | After <main> | Additional blocks |
Usage Examples
{{-- Add styles --}}
@push('styles')
<link rel="stylesheet" href="/my-styles.css">
@at('Modules/Shop/Resources/assets/scss/shop.scss')
@endpush
{{-- Add scripts --}}
@push('scripts')
<script src="/my-script.js"></script>
@at('Modules/Shop/Resources/assets/js/shop.js')
<script>
document.addEventListener('DOMContentLoaded', () => {
console.log('Page loaded');
});
</script>
@endpush
{{-- Add modal --}}
@push('modals')
<x-modal id="my-modal" title="Title">
...
</x-modal>
@endpush
{{-- Add meta tags --}}
@push('head')
<meta property="og:type" content="article">
<meta name="robots" content="noindex">
@endpushUseful Helpers in Templates
User
{{-- Check authorization --}}
@auth
<p>Hello, {{ user()->name }}!</p>
@else
<p>You are not logged in</p>
@endauth
{{-- Short syntax --}}
@guest
<a href="{{ url('login') }}">Login</a>
@endguestPermissions
@can('admin')
<a href="{{ url('admin') }}">Admin Panel</a>
@endcan
@cannot('admin')
<p>No access</p>
@endcannotURL and Assets
{{-- URL --}}
{{ url('/profile') }}
{{ url()->current() }}
{{-- Assets --}}
{{ asset('images/logo.png') }}
@asset('assets/js/app.js')
{{-- Path to theme --}}
@at(tt('assets/sass/app.scss'))Translations
@t('def.login')
@t('messages.welcome', ['name' => $user->name])
{{ __('messages.hello') }}Configuration
{{ config('app.name') }}
{{ config('app.description') }}
{{ config('app.logo') }}Navbar and Footer
{{-- All menu items --}}
@foreach (navbar()->all() as $item)
{{ $item['title'] }}
{{ $item['url'] }}
{{ $item['icon'] }}
{{ $item['children'] }}
@endforeach
{{-- Footer columns --}}
@foreach (footer()->all() as $column)
...
@endforeachBlade Directives
Conditions
@if ($condition)
...
@elseif ($other)
...
@else
...
@endif
@unless ($condition)
{{-- If condition is false --}}
@endunlessLoops
@foreach ($items as $item)
{{ $loop->index }} {{-- 0, 1, 2... --}}
{{ $loop->iteration }} {{-- 1, 2, 3... --}}
{{ $loop->first }} {{-- true if first --}}
{{ $loop->last }} {{-- true if last --}}
@endforeach
@forelse ($items as $item)
{{ $item }}
@empty
<p>No elements</p>
@endforelseIncluding Templates
@include('partials.sidebar')
@include('partials.card', ['title' => 'Hello'])
@includeWhen($condition, 'partials.sidebar')
@includeUnless($condition, 'partials.sidebar')PHP Code
@php
$total = $items->sum('price');
@endphp
{{ $total }}HTMX Integration
The layout is configured to work with HTMX — dynamic updates without page reloads.
How it Works
<body>has HTMX extension attributes.<main id="main">is the container for swap content.- Navigation uses
hx-boostfor SPA-like transitions.
Checking HTMX Request
@php
$isPartialRequest = request()->htmx()->isHtmxRequest();
@endphp
@if (!$isPartialRequest)
{{-- Full HTML (first load) --}}
@else
{{-- Content only (HTMX swap) --}}
@endifWith HTMX requests, header/footer are not re-rendered — only <main> is updated.