Welcome to the fourth part of creating an eCommerce website with Strapi, Jekyll, Tailwind CSS, and Snipcart series. Before reading this, you should catch up on the first, second, and third parts of this tutorial series.
In this part of the series, we will be creating our product catalog and single product views.
Creating our Product Catalog
Fetching All Products
In the third part of our series, we learned how to make a GET request to the Strapi server from the Jekyll frontend using the Strapi-Jekyll plugin. We will be using the same process to make a GET request for our products in this step.
Add the following collection to the Strapi endpoint in your config.yml file.
products:
type: productsThis code calls the endpoint that gets all our products from the Strapi backend.
Display All Products
Create a product.html file in your root folder. Add the following code snippets to the file.
---
layout: default
---
<div class="mt-6">
<h1 class="flex justify-center text-gray-600 font-semibold text-5xl mb-10">
Welcome to our store.
</h1>
{%- if strapi.collections.products.size > 0 -%}
<div
class="
grid grid-cols-1
gap-y-10
sm:grid-cols-2
gap-x-6
lg:grid-cols-3
xl:grid-cols-4
xl:gap-x-8
"
>
{%- for product in strapi.collections.products -%}
<a
key="{product.id}"
href="/product{{ product.slug | relative_url }}"
class="group mb-10"
>
<div
class="
w-full
aspect-w-1 aspect-h-1
bg-gray-200
rounded-lg
overflow-hidden
xl:aspect-w-7 xl:aspect-h-8
"
>
<img
src="http://localhost:1337{{ product.Image.url }}"
alt="{product.id}"
class="
w-full
h-60
object-center object-cover
group-hover:opacity-75
"
/>
</div>
<h3 class="text-center mt-4 text-sm text-gray-700">{{ product.name }}</h3>
<p class="text-center mt-1 text-lg font-medium text-gray-900">
${{ product.price }}
</p>
</a>
{%- endfor -%}
</div>
{%- endif -%}
</div>Again, as in the last part of our series, we used Liquid templating to loop through our products and Tailwind CSS to create a view for displaying the product.Also, we added the default layout in our frontmatter to apply our default layout to the page.
Access the product page by visiting http://localhost:4000/products. The page should look like this, depending on the types of products you added to your backend.
Creating Single Product Views
Fetching the Data for Single Products
To create a page for each product, we will need to create a collection for getting each product and displaying them on a page.
Add the following collection to the Strapi endpoint in your config.yml file.
product:
type: products
permalink: "/product/:slug/"
layout: product.html
output: trueWhat this collection does is that it gets a product and displays the product using the product.html layout. The permalink will serve as the link to the product page.
Now, navigate to the _layouts folder and create a product.html file. Add the following lines of code to the product.html file.
---
layout: default
---
<div>
<div
class="
mt-6
max-w-2xl
mx-auto
sm:px-6
lg:max-w-7xl
lg:px-8
lg:grid lg:grid-cols-3
lg:gap-x-8
"
>
<div
class="hidden aspect-w-3 aspect-h-4 rounded-lg overflow-hidden lg:block"
>
<img
src="http://localhost:1337{{ page.document.images[1].url }}"
alt="{product.images[0].alt}"
class="w-full h-full object-center object-cover"
/>
</div>
<div class="hidden lg:grid lg:grid-cols-1 lg:gap-y-8">
<div class="aspect-w-3 aspect-h-2 rounded-lg overflow-hidden">
<img
src="http://localhost:1337{{ page.document.images[2].url }}"
alt="{product.images[1].alt}"
class="w-full h-full object-center object-cover"
/>
</div>
<div class="aspect-w-3 aspect-h-2 rounded-lg overflow-hidden">
<img
src="http://localhost:1337{{ page.document.images[3].url }}"
alt="{product.images[2].alt}"
class="w-full h-full object-center object-cover"
/>
</div>
</div>
<div
class="
aspect-w-4 aspect-h-5
sm:rounded-lg
sm:overflow-hidden
lg:aspect-w-3 lg:aspect-h-4
"
>
<img
src="http://localhost:1337{{ page.document.images[0].url }}"
alt="{product.images[3].alt}"
class="w-full h-full object-center object-cover"
/>
</div>
</div>
<div
class="
max-w-2xl
mx-auto
pt-10
pb-16
px-4
sm:px-6
lg:max-w-7xl
lg:pt-16
lg:pb-24
lg:px-8
lg:grid lg:grid-cols-3 lg:grid-rows-[auto,auto,1fr]
lg:gap-x-8
"
>
<div class="lg:col-span-2 lg:border-r lg:border-gray-200 lg:pr-8"></div>
<div class="mt-4 lg:mt-0">
<h1
class="flex justify-center mb-5 text-2xl font-extrabold tracking-tight text-gray-900 sm:text-3xl"
>
{{ page.document.name }}
</h1>
<p class="text-3xl flex justify-center text-gray-900">
$ {{ page.document.price }}
</p>
<button
type="submit"
class="
mt-10
w-full
bg-blue-900
border border-transparent
rounded-md
py-3
px-8
flex
items-center
justify-center
text-base
font-medium
text-white
hover:bg-indigo-700
focus:outline-none
focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500
"
>
Add to cart
</button>
</div>
<div class="-mt-20 lg:pb-16 lg:col-start-1 lg:col-span-2 lg:border-r lg:border-gray-200 lg:pr-8">
<div>
<div class="space-y-6">
<p class="text-gray-900">{{ page.document.description }}</p>
</div>
</div>
<div class="mt-10">
<h2 class="text-lg font-bold text-gray-900">Details</h2>
<div class="mt-4 space-y-6">
<p class="text-sm text-gray-600">{{ page.document.additional_information }}</p>
</div>
</div>
</div>
</div>
</div>What this code does is that it gives each product page the default layout, which was specified in the frontmatter. Since this layout is associated with numerous products, not one, we will be specifying the template name as the {{ page.document }} instead.
This will allow all the products using the layout to take advantage of the layout. The product page should look like this, depending on the products you added to your backend server.
Conclusion
In this part of the series, we created our product catalog and single product views. The next part of the series will be about implementing the cart functionality in our website with Snipcart.
Here are the links to the final source code: Frontend Repository & Backend Repository