Blade is Laravel's templating engine. It compiles to plain PHP, offers template inheritance, and integrates with components introduced in modern Laravel versions for reusable UI pieces.
Layouts, Sections, and Yields
Most applications define a master layout in resources/views/layouts/app.blade.php with shared HTML structure, navigation, and asset tags.
Child views extend layouts and fill @section blocks that the layout @yield s into the final HTML.
Step 1: Create a master layout
The layout contains <!DOCTYPE html>, head meta tags, @vite(['resources/css/app.css', 'resources/js/app.js']), and a @yield('content') placeholder where page content appears.
Extract repeated navigation into partials with @include('partials.nav') or anonymous components so marketing and app areas can share branding without duplication.
@extends('layouts.app')
@section('content')
<h1>Dashboard</h1>
@endsection
Step 2: Stacks for scripts and styles
@push('scripts') in child views appends JavaScript to a @stack('scripts') in the layout. This keeps page-specific JS out of the global bundle.
Use @once inside stacks when partials might render multiple times. Prefer Vite for bundling and reserve stacks for tiny inline hooks or third-party widgets.
@push('scripts')
<script>initChart();</script>
@endpush
Step 3: Blade escaping and raw output
{{ $title }} escapes HTML to prevent XSS. {!! $trustedHtml !!} outputs unescaped content only for sanitized HTML from trusted sources.
Use @json($data) inside script tags safely. Never pass user input through {!! !!} without a dedicated HTML purifier.
<p>{{ $post->title }}</p>
Step 4: Control structures
@if, @foreach, @forelse, and @switch mirror PHP control flow with cleaner syntax. @empty inside @forelse shows a friendly message when collections are empty.
@continue and @break work inside loops. The @php directive is available but moving logic to controllers or view models keeps templates readable.
@forelse($posts as $post)
<li>{{ $post->title }}</li>
@empty
<p>No posts yet.</p>
@endforelse
Components and Slots
Blade components encapsulate markup and props. Class-based components live in app/View/Components while anonymous components sit in resources/views/components.
Slots let parents inject arbitrary markup into components, similar to web component patterns but compiled server-side.
Step 1: Anonymous components
Create resources/views/components/alert.blade.php and invoke it with <x-alert type="success">Saved!</x-alert>. Access props via @props(['type' => 'info']).
Components accept attributes merged onto the root element with {{ $attributes->merge(['class' => 'alert']) }} for flexible styling from the caller.
<x-alert type="danger">{{ $message }}</x-alert>
Step 2: Class-based components
php artisan make:component Card generates a class with render() returning the view. Constructor public properties become template variables automatically.
Use class components when you need dependency injection or computed properties that should not live in the Blade file.
class Card extends Component
{
public function render() { return view('components.card'); }
}
Step 3: Named and default slots
Define {{ $slot }} for default content and <x-slot name="footer"> for multiple regions. Layout components often use slots for sidebars and headers.
Document component APIs in comments at the top of the Blade file so designers know which props and slots are available.
<x-layout>
<x-slot name="title">Posts</x-slot>
Content here
</x-layout>
Step 4: View composers and sharing data
View::composer('partials.*', fn ($view) => $view->with('cartCount', Cart::count())) injects data without passing it from every controller.
Composers keep navigation badges and notification counts consistent. Register them in AppServiceProvider or dedicated providers.
View::composer('layouts.app', AppLayoutComposer::class);
Forms, Pagination, and Localization
Blade ships with helpers for forms, CSRF tokens, method spoofing, and pagination links that align with Laravel's routing and validation error bag.
Translate strings with @lang or __() helpers and store copies in lang/ files for multi-language applications.
Step 1: CSRF and method spoofing
Every POST form needs @csrf. PUT and DELETE from HTML forms use @method('PUT') because browsers only support GET and POST natively.
Laravel sets an XSRF-TOKEN cookie for JavaScript clients. Axios and fetch wrappers read it automatically when configured in resources/js/bootstrap.js.
<form method="POST" action="{{ route('posts.store') }}">
@csrf
...
</form>
Step 2: Display validation errors
@error('email') <span class="text-red-600">{{ $message }}</span> @enderror shows field-specific messages. $errors is always available when session middleware runs.
Use @if ($errors->any()) for summary banners at the top of forms. Old input repopulates with value="{{ old('title') }}" after failed validation.
@error('title')<p>{{ $message }}</p>@enderror
Step 3: Pagination views
Call {{ $posts->links() }} after paginating in the controller. Publish views with php artisan vendor:publish –tag=laravel-pagination and customize markup for Tailwind or Bootstrap.
Append query strings to pagination with ->withQueryString() so filters persist across pages. This is essential for admin tables with search parameters.
{{ $posts->withQueryString()->links() }}
Step 4: Localization in Blade
Use {{ __('messages.welcome') }} with lang/en/messages.php entries. Pass replacements like __('messages.greeting', ['name' => $user->name]).
Set locale per request in middleware for multi-tenant apps. Blade stays identical while translation files change per language.
{{ __('Welcome, :name', ['name' => $user->name]) }}
Aadyanex designs Laravel frontends with component libraries, accessible Blade partials, and Vite pipelines that keep UI consistent across admin and customer portals.
