Bagisto is one of the most popular Laravel e-commerce systems. In this tutorial, we will try to build a small demo e-shop with it, step-by-step, creating a custom design theme.
The example shop idea is taken from a "former official" store of Laravel products. At the time of writing this article, the Laravel team is rebuilding a new store, so not sure if this link is still working in the future, but: laravel.bigcartel.com
The end goal will look something like this:
This Laravel merchandise store has this functionality:
And to build it, we'll have to:
Notice: in this tutorial, we will not touch the checkout and payment processes, only the visual front look of the store with products. Maybe a topic for a future follow-up.
To install Bagisto, we've followed the official installation guide:
composer create-project bagisto/bagisto
After that, we modified our .env
file filling database credentials. Then we've run migrations:
php artisan migrate --seed
This already set quite a lot of things in place, but we've also had to run:
php artisan storage:link
To make sure that our images are accessible.
And lastly, we've just published all the assets:
php artisan vendor:publish --all
This step might have been overkill, but it's on the guide, so we've done it. This resulted in a store that looks like this:
Now that we have a store, we must make it look like the one we've shown in the beginning. To do that, we have to create a theme. This can be done like this:
Copy the folder resources/themes/default
to resources/themes/laravelshop
(or any other name you need)
Copy the folder public/themes/default
to public/themes/laravelshop
(or any other name you need)
Then open up config/themes.php
and add your theme to the list:
<?php return [ 'default' => 'default', 'themes' => [ 'default' => [ 'views_path' => 'resources/themes/default/views', 'assets_path' => 'public/themes/default/assets', 'name' => 'Default' ], 'velocity' => [ 'views_path' => 'resources/themes/velocity/views', 'assets_path' => 'public/themes/velocity/assets', 'name' => 'Velocity', 'parent' => 'default' ], 'laravelshop' => [ 'views_path' => 'resources/themes/laravelshop/views', 'assets_path' => 'public/themes/laravelshop/assets', 'name' => 'LaravelShop', 'parent' => 'default' ], ], 'admin-default' => 'default', 'admin-themes' => [ 'default' => [ 'views_path' => 'resources/admin-themes/default/views', 'assets_path' => 'public/admin-themes/default/assets', 'name' => 'Default' ] ]];
The last step is to log in to the admin panel and set the theme to the one we've just created:
You need to navigate to Settings
-> Channels
:
Then edit the default channel by scrolling until you find the Theme
field:
In this dropdown, you should select a theme named LaravelShop
(or whatever you've named your theme in config/themes.php
).
That's it! Now we have our custom theme running and can modify the shop!
Now that our theme is live, we must make it unique and specifically created for us. We'll have to modify the files in the resources/themes/laravelshop/views
folder to do that. This is where all the views are stored, and we can modify them to our liking.
Warning: looking from a pure Laravel MVC perspective, Bagisto Blade code may look like anti-pattern, because A LOT of logic is in Blade files. You will see many @php ... @endphp
blocks and <?php
calls in the Views, which is generally not recommended. But in this case, it makes perfect sense, as different blocks now are totally isolated and independent from other files.
Let's start by modifying the homepage. The initial step is to change what is displayed on the homepage. To do that, we need to go into channel settings (we've changed the theme there) and change the Home Page Content
value:
New value:
@include('shop::home.featured-products')
Then we need to clear the Footer Content
input and save. This will make our homepage update look like this:
Which already made our job easier by removing a lot of unnecessary elements. Next is the actual customization of the template:
The first thing we need to fix is a cart link. By default, it is not linking to the view cart page, so we will change this:
resources/themes/laravelshop/views/checkout/cart/mini-cart.blade.php
@php $cart = cart()->getCart();@endphp @if ($cart) @php $items = $cart->items; @endphp <a class="name" href="{{ route('shop.checkout.cart.index') }}"> {{ __('shop::app.header.cart') }} <span class="count"> ({{ $cart->items->count() }})</span> </a>@else <a class="name" href="{{ route('shop.checkout.cart.index') }}">{{ __('shop::app.minicart.cart') }}<span class="count"> ({{ __('shop::app.minicart.zero') }}) </span></a>@endif
This will give us a simple link to open the cart page. Next, we need to fix the whole navigation bar:
resources/themes/laravelshop/views/layouts/header/index.blade.php
<div class="header" id="header"> <div class="header-top"> <div class="right-content" style="width: 100%;"> <ul class="right-content-menu" style="width: 100%; text-align: center;"> <li> <a href="{{ route('shop.home.index') }}">Products</a> </li> <li class=""> <a href="{{ route('shop.cms.page', ['contact-us']) }}">Contact</a> </li> {!! view_render_event('bagisto.shop.layout.header.cart-item.before') !!} <li> @include('shop::checkout.cart.mini-cart') </li> {!! view_render_event('bagisto.shop.layout.header.cart-item.after') !!} </ul> <span class="menu-box"><span class="icon icon-menu" id="hammenu"></span></span> </div> </div> <div class="branding"> <a href="/" title="Home"> <img class="store-logo" srcset="https://assets.bigcartel.com/theme_images/54651347/laravel-logo.png?auto=format&fit=max&h=400&w=1068, https://assets.bigcartel.com/theme_images/54651347/laravel-logo.png?auto=format&fit=max&h=800&w=2136 2x" src="https://assets.bigcartel.com/theme_images/54651347/laravel-logo.png?auto=format&fit=max&h=400&w=1068" alt="laravel Home" style="max-height: 400px"> </a> </div></div>
Along with some CSS changes (Yes, we are modifying CSS in a public folder as that's recommended in their video tutorial):
public/themes/laravelshop/assets/css/shop.css
/* ... */ .header .header-top div.right-content .right-content-menu { -webkit-text-size-adjust: 100%; color: #111111; font-size: 16px; line-height: 1; text-align: center; font-family: "Varela Round", sans-serif; text-transform: uppercase; letter-spacing: 0.5px; box-sizing: border-box; display: flex; justify-content: center; list-style: none; margin: 0; padding: 0;} .header .header-top div.right-content .right-content-menu > li { -webkit-text-size-adjust: 100%; color: #111111; font-size: 16px; line-height: 1; font-family: "Varela Round", sans-serif; text-transform: uppercase; letter-spacing: 0.5px; list-style: none; box-sizing: border-box; border-bottom: 1px solid #b1b1b1; padding: 8px;} .header .header-top div.right-content .right-content-menu > li > a { -webkit-text-size-adjust: 100%; line-height: 1; font-family: "Varela Round", sans-serif; text-transform: uppercase; letter-spacing: 0.5px; list-style: none; box-sizing: border-box; background-color: transparent; transition: color 0.1s linear; cursor: pointer; color: #555555; display: block; font-size: 15px; padding: 8px; text-decoration: none;} .branding { -webkit-text-size-adjust: 100%; color: #111111; font-family: "Varela Round", sans-serif; line-height: 1; text-align: center; box-sizing: border-box; font-size: 20px; margin: 76px auto; text-transform: uppercase;}/* ... */
This will give us a header that looks like this:
To fix the footer, we need to modify a few files:
resources/themes/laravelshop/views/layouts/footer/footer.blade.php
<footer> <div class="wrapper"> <nav class="footer-nav" role="navigation" aria-label="Footer"> <ul class="footer-links"> <li><a href="{{ route('shop.home.index') }}">Home</a></li> <li><a href="{{ route('shop.home.index') }}">Products</a></li> <li><a href="{{ route('shop.cms.page', ['contact-us']) }}">Contact</a></li> <li><a href="{{ route('shop.checkout.cart.index') }}">Cart</a></li> </ul> </nav> </div></footer>
And add the following CSS:
public/themes/laravelshop/assets/css/shop.css
/* ... */ footer { -webkit-text-size-adjust: 100%; color: #111111; font-family: "Varela Round", sans-serif; font-size: 16px; line-height: 1; box-sizing: border-box; display: block;} footer > .wrapper { -webkit-text-size-adjust: 100%; color: #111111; font-family: "Varela Round", sans-serif; font-size: 16px; line-height: 1; box-sizing: border-box; padding: 0 24px; margin: 0 auto; max-width: 1100px; width: 100%;} footer > .wrapper > .footer-nav { -webkit-text-size-adjust: 100%; color: #111111; font-size: 16px; line-height: 1; box-sizing: border-box; border-top: 1px solid #b1b1b1; display: flex; flex-direction: column; align-items: center; font-family: "Varela Round", sans-serif; list-style: none; gap: 32px; margin: 0; padding: 40px 0;} .footer-nav ul.footer-links { -webkit-text-size-adjust: 100%; color: #111111; line-height: 1; font-family: "Varela Round", sans-serif; box-sizing: border-box; display: flex; justify-content: center; flex-wrap: wrap; list-style: none; margin: 0 0 24px 0; padding: 0; font-size: 16px;} .footer-nav ul.footer-links > li { -webkit-text-size-adjust: 100%; color: #111111; line-height: 1; font-family: "Varela Round", sans-serif; list-style: none; font-size: 16px; box-sizing: border-box;} .footer-nav ul.footer-links > li > a { -webkit-text-size-adjust: 100%; line-height: 1; font-family: "Varela Round", sans-serif; list-style: none; font-size: 16px; box-sizing: border-box; background-color: transparent; transition: color 0.1s linear; color: #111111; cursor: pointer; display: block; padding: 8px 16px; text-decoration: none;}
By doing this, we will have the following footer:
The last step to make our homepage look like the one in the demo is to update the product list. To do this, we need to modify the following files:
resources/themes/laravelshop/views/home/featured-products.blade.php
@php request()->query->remove('new'); request()->query->add([// 'featured' => 1, 'order' => 'rand', 'limit' => request()->get('count') ?? core()->getConfigData('catalog.products.homepage.no_of_featured_product_homepage'), ]); $products = app(\Webkul\Product\Repositories\ProductRepository::class)->getAll();@endphp @if ($products->count()) <section class="featured-products"> <div class="featured-grid product-grid-4"> @foreach ($products as $productFlat) @include ('shop::products.list.card', ['product' => $productFlat]) @endforeach </div> </section>@endif
With CSS, we need to set the grid to three columns:
public/themes/laravelshop/assets/css/shop.css
/* ... */ .main-container-wrapper .product-grid-3, .main-container-wrapper .product-grid-4 { display: grid; grid-template-columns:repeat(auto-fill, minmax(30%, 1fr)); /* 30% of the container width */ justify-items: center}
This brought us closer to what we need:
But we still need to style each product box:
resources/themes/laravelshop/views/products/list/card.blade.php
{!! view_render_event('bagisto.shop.products.list.card.before', ['product' => $product]) !!} <div class="product-card"> <?php $productBaseImage = product_image()->getProductBaseImage($product); ?> @if ( ! $product->getTypeInstance()->haveDiscount() && $product->new ) <div class="sticker new"> {{ __('shop::app.products.new') }} </div> @endif <div class="product-image" style="background: none;"> <a href="{{ route('shop.productOrCategory.index', $product->url_key) }}" title="{{ $product->name }}"> <img src="{{ $productBaseImage['medium_image_url'] }}" onerror="this.src='{{ asset('vendor/webkul/ui/assets/images/product/medium-product-placeholder.png') }}'" alt="" height="500"/> </a> </div> <div class="product-information"> <div class="product-list-thumb-info"> <div class="product-list-item-background"></div> <div class="product-list-thumb-info-headers"> <div class="product-list-thumb-name"> <a href="{{ route('shop.productOrCategory.index', $product->url_key) }}" title="{{ $product->name }}"> <span> {{ $product->name }} </span> </a> </div> <div class="product-list-thumb-price"> @include ('shop::products.price', ['product' => $product]) </div> </div> </div> </div> </div> {!! view_render_event('bagisto.shop.products.list.card.after', ['product' => $product]) !!}
And, of course, add CSS to style it:
public/themes/laravelshop/assets/css/shop.css
/* ... */ .product-list-thumb-info { -webkit-text-size-adjust: 100%; font-family: "Varela Round", sans-serif; word-break: break-word; color: #111111; cursor: pointer; box-sizing: border-box; font-size: 18px; line-height: 1.25em; padding: 16px 8px; position: relative; text-align: center;} .product-list-thumb-info-headers { -webkit-text-size-adjust: 100%; font-family: "Varela Round", sans-serif; word-break: break-word; color: #111111; cursor: pointer; font-size: 18px; line-height: 1.25em; text-align: center; box-sizing: border-box;} .product-list-thumb-name { -webkit-text-size-adjust: 100%; font-family: "Varela Round", sans-serif; word-break: break-word; color: #111111; cursor: pointer; font-size: 18px; line-height: 1.25em; text-align: center; box-sizing: border-box; overflow-wrap: break-word; position: relative; text-transform: uppercase; letter-spacing: 1px;} .product-list-thumb-name:after { bottom: -8px; content: ""; background-color: #111111; height: 1px; left: 50%; opacity: 0.5; position: absolute; transform: translateX(-50%); width: 16px;} .product-list-thumb-name a { color: #111111;} .product-list-thumb-price { -webkit-text-size-adjust: 100%; word-break: break-word; color: #111111; cursor: pointer; line-height: 1.25em; text-align: center; box-sizing: border-box; font-family: "Montserrat", sans-serif; font-size: 16px; margin-top: 16px;}
Then as a last step, we need to update how we display prices:
public/themes/laravelshop/assets/css/shop.css
/* ... */ .price-label { display: none;} .product-price > .special-price, .product-price > .regular-price { color: #111111;}
And we are done! We have a nice-looking product grid:
Another place to improve is the product page. We are aiming to have something like this:
Yet, we are starting with this:
Let's start with modifying the gallery:
resources/themes/laravelshop/views/products/view/gallery.blade.php
@inject ('wishListHelper', 'Webkul\Customer\Helpers\Wishlist') @php $images = product_image()->getGalleryImages($product); $videos = product_video()->getVideos($product); $images = array_merge($images, $videos);@endphp {!! view_render_event('bagisto.shop.products.view.gallery.before', ['product' => $product]) !!} <div class="product-image-group"> <product-gallery></product-gallery></div> {!! view_render_event('bagisto.shop.products.view.gallery.after', ['product' => $product]) !!} @push('scripts') <script type="text/x-template" id="product-gallery-template"> <li > <img :src="currentLargeImageUrl" id="pro-img" :data-image="currentOriginalImageUrl" alt="" class="product-image"/> </li> </script> <script> let galleryImages = @json($images); Vue.component('product-gallery', { template: '#product-gallery-template', data: function () { return { images: galleryImages, thumbs: [], currentLargeImageUrl: '', currentOriginalImageUrl: '', currentVideoUrl: '', currentType: '', counter: { up: 0, down: 0, }, is_move: { up: true, down: true, } } }, watch: { 'images': function (newVal, oldVal) { this.changeImage(this.images[0]); } }, created: function () { this.changeImage(this.images[0]); }, methods: { changeImage: function (image) { this.currentType = image.type; if (image.type == 'video') { this.currentVideoUrl = image.video_url; this.currentLargeImageUrl = image.large_image_url = image.video_url; } else { this.currentLargeImageUrl = image.large_image_url; this.currentOriginalImageUrl = image.original_image_url; } if ($(window).width() > 580 && image.original_image_url) { $('img#pro-img').data('zoom-image', image.original_image_url).ezPlus(); } }, } }); </script>@endpush
Then we will modify the product page itself:
resources/themes/laravelshop/views/products/view.blade.php
@php use Illuminate\Support\Str; @endphp @extends('shop::layouts.master') @section('page_title') {{ trim($product->meta_title) != "" ? $product->meta_title : $product->name }}@stop @section('seo') <meta name="description" content="{{ trim($product->meta_description) != "" ? $product->meta_description : Str::limit(strip_tags($product->description), 120, '') }}"/> <meta name="keywords" content="{{ $product->meta_keywords }}"/> @if (core()->getConfigData('catalog.rich_snippets.products.enable')) <script type="application/ld+json"> {{ app('Webkul\Product\Helpers\SEO')->getProductJsonLd($product) }} </script> @endif <?php $productBaseImage = product_image()->getProductBaseImage($product); ?> <meta name="twitter:card" content="summary_large_image"/> <meta name="twitter:title" content="{{ $product->name }}"/> <meta name="twitter:description" content="{!! htmlspecialchars(trim(strip_tags($product->description))) !!}"/> <meta name="twitter:image:alt" content=""/> <meta name="twitter:image" content="{{ $productBaseImage['medium_image_url'] }}"/> <meta property="og:type" content="og:product"/> <meta property="og:title" content="{{ $product->name }}"/> <meta property="og:image" content="{{ $productBaseImage['medium_image_url'] }}"/> <meta property="og:description" content="{!! htmlspecialchars(trim(strip_tags($product->description))) !!}"/> <meta property="og:url" content="{{ route('shop.productOrCategory.index', $product->url_key) }}"/>@stop @section('content-wrapper') {!! view_render_event('bagisto.shop.products.view.before', ['product' => $product]) !!} <section class="product-detail" style="background: #F3F3F3; padding-bottom: 64px; padding-top: 64px;"> <div class="layouter"> <product-view> <div class="product-wrapper"> @csrf() <input type="hidden" name="product_id" value="{{ $product->id }}"> <input type="hidden" name="quantity" value="1"> <div class="product-page"> <div class="product-page-headings"> <h1 class="product-title has-dash">{{ $product->name }}</h1> <div class="product-price"> @include ('shop::products.price', ['product' => $product]) </div> </div> <div class="product-images"> <ul class="slides"> @include ('shop::products.view.gallery') </ul> </div> <div class="product-details"> <div class="product-description"> {!! $product->description !!} </div> <div class="select"> @include ('shop::products.view.configurable-options') </div> <button class="button add-to-cart-button addtocart" type="submit" data-add-title="Add to Cart" data-sold-title="Sold out">Add to Cart </button> </div> </div> </div> </product-view> </div> </section> {!! view_render_event('bagisto.shop.products.view.after', ['product' => $product]) !!}@endsection @push('scripts') <script type="text/x-template" id="product-view-template"> <form method="POST" id="product-form" action="{{ route('shop.cart.add', $product->id) }}" @click="onSubmit($event)"> <input type="hidden" name="is_buy_now" v-model="is_buy_now"> <slot></slot> </form> </script> <script type="text/x-template" id="quantity-changer-template"> <div class="quantity control-group" :class="[errors.has(controlName) ? 'has-error' : '']"> <label class="required">{{ __('shop::app.products.quantity') }}</label> <span class="quantity-container"> <button type="button" class="decrease" @click="decreaseQty()">-</button> <input ref="quantityChanger" :name="controlName" :model="qty" class="control" v-validate="validations" data-vv-as=""{{ __('shop::app.products.quantity') }}"" @keyup="setQty($event)"> <button type="button" class="increase" @click="increaseQty()">+</button> </span> <span class="control-error" v-if="errors.has(controlName)">@{{ errors.first(controlName) }}</span> </div> </script> <script> Vue.component('product-view', { template: '#product-view-template', inject: ['$validator'], data: function () { return { is_buy_now: 0, } }, methods: { onSubmit: function (e) { if (e.target.getAttribute('type') != 'submit') return; e.preventDefault(); var this_this = this; this.$validator.validateAll().then(function (result) { if (result) { this_this.is_buy_now = e.target.classList.contains('buynow') ? 1 : 0; setTimeout(function () { console.log(document.getElementById('product-form')) document.getElementById('product-form').submit(); }, 0); } }); } } }); Vue.component('quantity-changer', { template: '#quantity-changer-template', inject: ['$validator'], props: { controlName: { type: String, default: 'quantity' }, quantity: { type: [Number, String], default: 1 }, minQuantity: { type: [Number, String], default: 1 }, validations: { type: String, default: 'required|numeric|min_value:1' } }, data: function () { return { qty: this.quantity } }, mounted: function () { this.$refs.quantityChanger.value = this.qty > this.minQuantity ? this.qty : this.minQuantity; }, watch: { qty: function (val) { this.$refs.quantityChanger.value = !isNaN(parseFloat(val)) ? val : 0; this.qty = !isNaN(parseFloat(val)) ? this.qty : 0; this.$emit('onQtyUpdated', this.qty); this.$validator.validate(); } }, methods: { setQty: function ({target}) { this.qty = parseInt(target.value); }, decreaseQty: function () { if (this.qty > this.minQuantity) this.qty = parseInt(this.qty) - 1; }, increaseQty: function () { this.qty = parseInt(this.qty) + 1; } } }); window.onload = function () { var thumbList = document.getElementsByClassName('thumb-list')[0]; var thumbFrame = document.getElementsByClassName('thumb-frame'); var productHeroImage = document.getElementsByClassName('product-hero-image')[0]; if (thumbList && productHeroImage) { for (let i = 0; i < thumbFrame.length; i++) { thumbFrame[i].style.height = (productHeroImage.offsetHeight / 4) + "px"; thumbFrame[i].style.width = (productHeroImage.offsetHeight / 4) + "px"; } if (screen.width > 720) { thumbList.style.width = (productHeroImage.offsetHeight / 4) + "px"; thumbList.style.minWidth = (productHeroImage.offsetHeight / 4) + "px"; thumbList.style.height = productHeroImage.offsetHeight + "px"; } } window.onresize = function () { if (thumbList && productHeroImage) { for (let i = 0; i < thumbFrame.length; i++) { thumbFrame[i].style.height = (productHeroImage.offsetHeight / 4) + "px"; thumbFrame[i].style.width = (productHeroImage.offsetHeight / 4) + "px"; } if (screen.width > 720) { thumbList.style.width = (productHeroImage.offsetHeight / 4) + "px"; thumbList.style.minWidth = (productHeroImage.offsetHeight / 4) + "px"; thumbList.style.height = productHeroImage.offsetHeight + "px"; } } } }; </script>@endpush
And, of course, add the required CSS:
public/themes/laravelshop/assets/css/shop.css
/* ... */ .product-page { -webkit-text-size-adjust: 100%; color: #111111; font-family: "Varela Round", sans-serif; font-size: 16px; line-height: 1; box-sizing: border-box; padding-bottom: 30px; position: relative;} .product-page { padding-bottom: 30px; position: relative;} .product-page:before, .product-page:after { content: ""; display: table; clear: both;} .product-page .product-page-headings { float: left; max-width: 35%; padding-right: 40px; padding-left: 0; width: 100%;} .product-page .product-title { -webkit-text-size-adjust: 100%; font-family: "Varela Round", sans-serif; box-sizing: border-box; font-size: 2em; color: #111111; font-weight: normal; line-height: 1.4em; margin: 0; padding: 0; position: relative; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 24px; text-align: center;} .product-page .product-price { font-family: "Montserrat", sans-serif; margin-bottom: 32px; text-align: center; font-size: 23px; font-weight: normal; line-height: 1.4em;} .product-wrapper { -webkit-text-size-adjust: 100%; color: #111111; font-family: "Varela Round", sans-serif; font-size: 16px; line-height: 1; box-sizing: border-box; padding: 0 24px; margin: 0 auto; max-width: 1100px; width: 100%;} h1.has-dash:after { bottom: -8px; content: ""; background-color: #111111; height: 2px; left: 50%; position: absolute; transform: translateX(-50%); width: 24px;} .product-price { -webkit-text-size-adjust: 100%; color: #111111; box-sizing: border-box; font-family: "Montserrat", sans-serif; margin-bottom: 32px; text-align: center; font-size: 23px; font-weight: normal; line-height: 1.4em;} .product-images { -webkit-text-size-adjust: 100%; color: #111111; font-family: "Varela Round", sans-serif; font-size: 16px; line-height: 1; box-sizing: border-box; float: right; max-width: 63%; padding-left: 24px; padding-right: 0; position: relative; width: 100%;} .product-images .slides { -webkit-text-size-adjust: 100%; color: #111111; font-family: "Varela Round", sans-serif; font-size: 16px; line-height: 1; box-sizing: border-box; margin: 0; padding: 0; list-style: none;} .product-images .slides li { -webkit-text-size-adjust: 100%; color: #111111; font-family: "Varela Round", sans-serif; font-size: 16px; line-height: 1; box-sizing: border-box; margin: 0; padding: 0; list-style: none;} .product-image { -webkit-text-size-adjust: 100%; color: #111111; font-family: "Varela Round", sans-serif; font-size: 16px; line-height: 1; list-style: none; box-sizing: border-box; border-style: none; border-radius: 4px; display: block; margin-bottom: 32px; max-width: 100%; width: 100%;} .product-details { -webkit-text-size-adjust: 100%; color: #111111; font-family: "Varela Round", sans-serif; font-size: 16px; line-height: 1; box-sizing: border-box; clear: left; float: left; max-width: 35%; padding-right: 24px; padding-left: 0; width: 100%; margin-bottom: 0;} .product-description { -webkit-text-size-adjust: 100%; color: #111111; box-sizing: border-box; font-family: "Montserrat", sans-serif; font-size: 16px; line-height: 1.5em; margin-bottom: 32px;} .add-to-cart-button { -webkit-text-size-adjust: 100%; box-sizing: border-box; overflow: visible; margin: 0; cursor: pointer; border: none; border-radius: 4px; font-family: "Varela Round", sans-serif; transition: color, background-color 0.1s linear; background: #000000; color: #FFFFFF; font-size: 15px; height: 58px; line-height: 58px; max-width: 100%; padding: 0 16px; text-align: center; text-transform: uppercase; letter-spacing: 0.5px; -webkit-appearance: button; display: block; width: 100%;} .control-group .control { -webkit-text-size-adjust: 100%; box-sizing: border-box; font-size: 100%; text-transform: none; cursor: pointer; appearance: none; background: none; border-radius: 4px; color: #111111; font-family: "Varela Round", sans-serif; line-height: normal; padding: 0 66px 0 16px; position: relative; width: 100%; z-index: 2; border: 2px solid #111111; height: 58px; margin-bottom: 16px; max-width: 100%;} .attributes label { display: none;}
Once we are done, we will have a product page that looks like this:
And while we can agree that it's not perfect - it's close enough and displays how easy it is to customize Bagisto to your liking. If you are following this process - take a look at the following steps:
resources/themes/laravelshop/views/checkout/cart/index.blade.php
resources/themes/laravelshop/views/checkout/onepage.blade.php
resources/themes/laravelshop/views/checkout/onepage/payment.blade.php
resources/themes/laravelshop/views/checkout/onepage/review.blade.php
resources/themes/laravelshop/views/checkout/onepage/shipping.blade.php
resources/themes/laravelshop/views/checkout/onepage/total.blade.php
You should have an idea of how things are structured and where you can find the files you need to modify. You may want to reference Controllers or modify them too. For example, if you're going to modify the Cart Controller, you can find it here: packages/Webkul/Checkout/src/Http/Controllers/CartController.php
.
As we all know, there's way more to creating themes than what we just did. For example, we haven't touched the Cart or Checkout systems.
But with this tutorial, we aimed to show you how easy it is to start creating themes for Bagisto. And this is, of course, only some of the pages. Creating an entire theme would require a lot more checks:
So these can be your "homework", as you now understand how Bagisto themes work.
If you want more tutorials on Bagisto, including the cart/checkout processes, let us know in the comments, and we will consider it in the future.