Skip to content

Quick Start: Build Your First Theme

This guide walks you through creating a working theme from scratch in under 15 minutes. By the end, you'll have a fully functional homepage, header, and footer with live data from the store.

Prerequisites

  • Basic knowledge of HTML, CSS, Bootstrap 5
  • Understanding of Laravel Blade syntax
  • Access to the lara-app codebase

Step 1: Set Up Your Theme Directory

All theme files live in lara-app/resources/views/. The application resolves templates from here based on the active theme name. For this guide, we'll create a theme called my-theme.

Create the following directory structure:

lara-app/resources/views/
├── layout/
│   ├── layout.blade.php     ← The master layout (required)
│   ├── header.blade.php     ← Header partial
│   └── footer.blade.php     ← Footer partial
├── template/
│   └── home.blade.php       ← Homepage template (required)
└── partial/
    └── homepageproduct.blade.php  ← Product card partial

Step 2: Create the Master Layout

The master layout is the HTML shell for every page. It defines the <html>, <head>, and <body> tags, and @yields named sections for child pages to fill.

Create resources/views/layout/layout.blade.php:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    {{-- ✅ Page-specific title (overridable per page) --}}
    @yield('headtitle')

    {{-- ✅ Site-wide SEO meta tags --}}
    <meta name="description" content="{{ $page->settings->metaDescription ?? '' }}">
    <meta name="keywords" content="{{ $page->settings->metaKeywords ?? '' }}">

    {{-- ✅ Open Graph tags for social sharing (overridable per page) --}}
    @yield('headmeta')

    {{-- ✅ Bootstrap 5 CSS --}}
    <link rel="stylesheet" href="{{ cdn_asset('css/bootstrap.min.css') }}">

    {{-- ✅ Theme-specific CSS --}}
    <link rel="stylesheet" href="{{ theme_asset('css/style.css') }}">

    {{-- ✅ Additional page-specific CSS --}}
    @yield('style')

    {{-- ✅ Additional page-specific links --}}
    @yield('headlink')
</head>
<body>

    {{-- ✅ Site Notification Banner (optional) --}}
    @php $notification = getSiteNotification(); @endphp
    @if($notification->status)
        <div style="background: {{ $notification->backgroundcolor }}; color: {{ $notification->fontcolor }}; text-align: center; padding: 8px;">
            {!! $notification->Content !!}
        </div>
    @endif

    {{-- ✅ Include the header --}}
    @include('layout.header')

    {{-- ✅ Flash Messages --}}
    @php $flash = flashMessenger(); @endphp
    @foreach($flash->getSuccessMessages() as $msg)
        <div class="alert alert-success">{{ $msg }}</div>
    @endforeach
    @foreach($flash->getErrorMessages() as $msg)
        <div class="alert alert-danger">{{ $msg }}</div>
    @endforeach

    {{-- ✅ Main Content Area - this is where page templates inject their content --}}
    <main>
        @yield('content')
    </main>

    {{-- ✅ Include the footer --}}
    @include('layout.footer')

    {{-- ✅ jQuery and Bootstrap JS --}}
    <script src="{{ cdn_asset('js/jquery.min.js') }}"></script>
    <script src="{{ cdn_asset('js/bootstrap.bundle.min.js') }}"></script>

    {{-- ✅ Theme-specific JS --}}
    <script src="{{ theme_asset('js/app.js') }}"></script>

    {{-- ✅ Google Analytics (auto-injects the tracking code if configured in admin) --}}
    {!! googleAnalytics() !!}

    {{-- ✅ Additional page-specific scripts --}}
    @yield('script')

</body>
</html>

Step 3: Create the Header Partial

Create resources/views/layout/header.blade.php:

<header>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container">

            {{-- ✅ Store Logo: uses $themes->header_image config from admin --}}
            <a class="navbar-brand" href="{{ customUrl('home') }}">
                @if(getPath($themes->header_image ?? null))
                    <img src="{{ getPath($themes->header_image) }}" alt="{{ $page->settings->siteTitle ?? 'Store' }}" height="50">
                @else
                    {{ $page->settings->siteTitle ?? 'My Store' }}
                @endif
            </a>

            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainNav">
                <span class="navbar-toggler-icon"></span>
            </button>

            <div class="collapse navbar-collapse" id="mainNav">
                {{-- ✅ Dynamic top menus from admin panel --}}
                <ul class="navbar-nav me-auto">
                    @foreach(getMenu('top') as $menu)
                        <li class="nav-item">
                            <a class="nav-link" href="{{ $menu['menu_url'] ?? '#' }}">
                                {{ $menu['menuName'] }}
                            </a>
                        </li>
                    @endforeach
                </ul>

                {{-- ✅ Cart Icon with live item count --}}
                <div class="d-flex">
                    @if(auth('customer')->check())
                        <span class="text-light me-3">Hello, {{ lmcUserDisplayName() }}</span>
                        <a href="{{ customUrl('logout') }}" class="btn btn-outline-light btn-sm me-2">Logout</a>
                    @else
                        <a href="{{ customUrl('login') }}" class="btn btn-outline-light btn-sm me-2">Login</a>
                        <a href="{{ customUrl('register') }}" class="btn btn-light btn-sm me-2">Register</a>
                    @endif

                    {{-- ✅ Cart count badge --}}
                    @if(!$page->settings->catalogMode)
                        <a href="{{ customUrl('cart_list') }}" class="btn btn-warning btn-sm">
                            🛒 Cart
                            <span class="badge bg-danger">{{ getCart('cartProductQuantity') }}</span>
                        </a>
                    @endif
                </div>
            </div>
        </div>
    </nav>
</header>

Create resources/views/layout/footer.blade.php:

<footer class="bg-dark text-light py-4 mt-5">
    <div class="container">
        <div class="row">
            <div class="col-md-6">
                <h5>{{ $page->settings->siteTitle ?? 'My Store' }}</h5>
            </div>
            <div class="col-md-6 text-md-end">
                {{-- ✅ Dynamic footer menus from admin panel --}}
                @foreach(getMenu('bottom') as $menu)
                    <a href="{{ $menu['menu_url'] ?? '#' }}" class="text-light me-3">
                        {{ $menu['menuName'] }}
                    </a>
                @endforeach
            </div>
        </div>
    </div>
</footer>

Step 5: Create the Homepage Template

Create resources/views/template/home.blade.php:

@extends('layout.layout')

{{-- ✅ Override the page title --}}
@section('headtitle')
    <title>{{ $page->settings->siteTitle ?? 'Welcome' }}</title>
@endsection

@section('content')
<div class="container mt-4">

    {{-- ✅ Hero Banner Image (configured in admin panel) --}}
    @if(getPath($themes->banner_image ?? null))
        <div class="mb-4">
            <img src="{{ getPath($themes->banner_image) }}" alt="Banner" class="img-fluid w-100 rounded">
        </div>
    @endif

    {{-- ✅ Featured Products Section --}}
    <h2 class="mb-3">Featured Products</h2>
    <div class="row">
        @foreach(featureProducts(8) as $product)
            <div class="col-md-3 mb-4">
                @include('partial.homepageproduct', ['product' => $product])
            </div>
        @endforeach
    </div>

    {{-- ✅ Latest Products Section --}}
    <h2 class="mt-5 mb-3">New Arrivals</h2>
    <div class="row">
        @foreach(latestProducts() as $product)
            <div class="col-md-3 mb-4">
                @include('partial.homepageproduct', ['product' => $product])
            </div>
        @endforeach
    </div>

</div>
@endsection

Step 6: Create the Product Card Partial

Create resources/views/partial/homepageproduct.blade.php:

{{--
    Expected variable: $product (array from featureProducts(), latestProducts(), etc.)
    Keys: name, image, normalPrice, specialPrice, detailUrl, addToCartUrl, reviewDisplay, availability
--}}
<div class="card h-100">
    {{-- Product Image --}}
    <a href="{{ $product['detailUrl'] ?? '#' }}">
        <img src="{{ $product['image'] ?? noproductimage() }}"
             alt="{{ getAlt($product['image'] ?? null, $product['name'] ?? 'Product') }}"
             class="card-img-top"
             style="height: 200px; object-fit: contain;">
    </a>

    <div class="card-body d-flex flex-column">
        {{-- Product Name --}}
        <h6 class="card-title">
            <a href="{{ $product['detailUrl'] ?? '#' }}">
                {{ tagShortText($product['name'] ?? '', 50) }}
            </a>
        </h6>

        {{-- Star Rating (if reviewed) --}}
        @if(!empty($product['reviewDisplay']))
            <div class="small mb-1">{!! $product['reviewDisplay'] !!}</div>
        @endif

        {{-- Price --}}
        <div class="mt-auto">
            @if(($product['discountPercent'] ?? 0) > 0)
                <span class="text-muted text-decoration-line-through">
                    ${{ tagPrice($product['normalPrice'] ?? 0) }}
                </span>
                <span class="text-danger fw-bold ms-1">
                    ${{ tagPrice($product['specialPrice'] ?? 0) }}
                </span>
            @else
                <span class="fw-bold">
                    ${{ tagPrice($product['normalPrice'] ?? $product['specialPrice'] ?? 0) }}
                </span>
            @endif
        </div>

        {{-- Add to Cart Button (only if not in catalog mode) --}}
        @if(!$page->settings->catalogMode && ($product['availability'] ?? 0) > 0)
            <a href="{{ $product['addToCartUrl'] ?? '#' }}" class="btn btn-primary btn-sm mt-2">
                Add to Cart
            </a>
        @else
            <a href="{{ $product['detailUrl'] ?? '#' }}" class="btn btn-outline-secondary btn-sm mt-2">
                View Details
            </a>
        @endif
    </div>
</div>

🎉 You're Done!

Visit http://laravel.tagateway.com to see your theme in action.

What you built

  • ✅ A master layout with header, footer, and flash messages
  • ✅ A homepage pulling live featured and latest products
  • ✅ A product card partial with pricing, images, and add-to-cart
  • ✅ Dynamic menu navigation from the admin panel
  • ✅ Cart item count in the header

Next Steps