This article is a guest series by the great Ekene Eze. He’s leading the Developer Experience team at Flutterwave and wrote this blog post through the Write for the Community program.
This series will walk you through the processes of setting up your own food ordering application and by extension any e-commerce app using modern development tools like Strapi, Gridsome and Snipcart.
Table of Contents: 1. Part 1 - Generating a Strapi app and creating products 2. Part 2 - Setting up a Gridsome project 3. Part 3 - Consuming products with Gridsome and GraphQL 4. Part 4 - Creating single product views with Gridsome templates 5. Part 5 - Implementing cart and checkout with Snipcart 6. Part 6 - Deploying the apps
In the last part, we were able to create single product view pages where customers can get more information about each product. We also set up navigation for shop and support pages respectively. In this part, we will hook up our food ordering application with Snipcart to ensure that customers can place orders for our meals.
Like I mentioned at the beginning of this series, Snipcart is a simple e-commerce solution that makes it possible for developers to add fully customizable checkout experiences to any website.
In this part of the series, we'll use Snipcart to add checkout functionalities to our existing Gridsome application. To do that, first, you need to create a free Snipcart account.
Install Snipcart
Next, let's install Snipcart. Create an index.html file in the src folder and update it with the code snippet below:
1<!-- src/index.html -->
2<!DOCTYPE html>
3<html ${htmlAttrs}>
4 <head>
5 ${head}
6 <link rel="preconnect" href="https://app.snipcart.com" />
7 <link rel="preconnect" href="https://cdn.snipcart.com" />
8 <link
9 rel="stylesheet"
10 href="https://cdn.snipcart.com/themes/v3.0.23/default/snipcart.css"
11 />
12 </head>
13 <body ${bodyAttrs}>
14 ${app} ${scripts}
15 <div
16 id="snipcart"
17 data-api-key="MDg5MmMwOWQtOTIxZi00ZTE4LWE3MmUtNDlkZjcyZmQ2OThjNjM3Mzg2NDU1MDUyODI0NjM2"
18 hidden
19 ></div>
20 <script
21 async
22 src="https://cdn.snipcart.com/themes/v3.0.23/default/snipcart.js"
23 ></script>
24 </body>
25</html>
What we've done here is add the required Snipcart JavaScript and CSS assets to our Gridsome application. Adding them will automatically install and make Snipcart available in the project.
Next, we need to make Snipcart available globally in our application. To do this, the Snipcart team recommends using a hidden element in a central location such that when we define Snipcart there, it will be globally available across all our website pages. That location in this project, is the Default.vue
file. Since this layout covers every part of our application, simply open up the file and add this div element to it:
1<!-- src/layouts/Defualt.vue -->
2<div
3 hidden
4 id="snipcart"
5 data-api-key="YOUR_SNIPCART_API_KEY_HERE"
6></div>
You can get your Snipcart API key from your dashboard. Now that we have Snipcart installed, let's go ahead and modify our application to introduce the behavioural changes we want on the app.
First, when the Add to cart button is clicked, we want to immediately add that particular product to cart and equally display the cart so the user can checkout if they want to. To do that, we need to update the button within our src/components/Products.vue
file:
1<!-- src/components/products.vue -->
2<v-card-actions>
3 <v-btn
4 rounded
5 outlined
6 color="orange"
7 text
8 class="snipcart-add-item"
9 :data-item-id="edge.node.id"
10 :data-item-description="edge.node.description"
11 :data-item-image="`http://localhost:1337${edge.node.image}`"
12 :data-item-price="edge.node.price"
13 :data-item-name="edge.node.title"
14 >
15 Add to cart
16 </v-btn>
17</v-card-actions>
All we did here is add the snipcart-add-item class to the button and pass in the data- attributes to it as well. Adding the snipcart-add-item class to any HTML element tells Snipcart to react a certain way when that element is clicked. In this case, add the data contents of this element to the cart. We supply the values for the data attributes directly from our data layer.
Because we have this button available within the single product pages, we'll need to make the same updates in the Product template:
1<!-- src/templates/product.vue -->
2<v-card-actions>
3 <v-btn
4 rounded
5 outlined
6 color="orange"
7 text
8 class="snipcart-add-item"
9 :data-item-id="this.$page.product.id"
10 :data-item-description="this.$page.product.description"
11 :data-item-image="
12 `http://localhost:1337${this.$page.product.image}`
13 "
14 :data-item-price="this.$page.product.price"
15 :data-item-name="this.$page.product.title"
16 >
17 Add to cart
18 </v-btn>
19 <v-spacer></v-spacer>
20 <v-rating
21 :value="this.$page.product.rating"
22 color="amber"
23 dense
24 half-increments
25 readonly
26 size="14"
27 ></v-rating>
28 <span>
29 <v-card-title>${{ this.$page.product.price }}</v-card-title>
30 </span>
31</v-card-actions>
When this button is clicked, from the product listing page or from the single product detail page, the product will be added to the cart by Snipcart and the shopping cart will be displayed for review.
You might ask, how do we show the cart logo or display prices of items that are added to cart so that customers can shop on a budget. Let's see how to do that.
Within the Default.vue file
, update the snippet to account for a cart logo and a price field. Hence, add this snippet immediately after the search field:
1<!-- src/layout/Default.vue -->
2<v-btn class=" snipcart-checkout" icon>
3 <v-icon>mdi-cart</v-icon>
4 <span class="snipcart-total-items"></span>
5 <span class="snipcart-total-price"></span>
6</v-btn>
Here, we wrapped the cart icon in a button element with a snipcart-checkout class. This is just a personal preference to ensure that users can click on the cart icon to bring up the cart. After the cart icon, we provisioned two more fields to display the number of items in cart, and the total price of the items in cart respectively. These are all just template classes, let's move down to the script section of the file and add some logic to it:
1<!-- src/layout/Default.vue -->
2
3<script>
4export default {
5 data() {
6 return {
7 totalPrice: 0,
8 };
9 },
10 methods: {
11 getTotalPrice() {
12 return Snipcart.store.getState().cart.total;
13 },
14 },
15 mounted() {
16 this.totalPrice = this.getTotalPrice();
17 },
18};
19</script>
The code snippet above simply calculates the total price of all the items in the cart and renders it in the field with the class of snipcart-total-price. You can repeat the same process to calculate the total number of items in cart, but we'll go ahead and save these changes. If you check back on the browser for the recent changes, you will notice that both the cart icon and the price is showing up just as expected:
In this section, we have successfully integrated Snipcart into our Gridsome project and made it possible for customers to place orders for our meals. We started by adding Snipcart's required JavaScript and CSS files to our project. We made it available globally in the project's layout and finally implemented the add to cart functionality. In the next part, we'll look at how to deploy these applications and have users use them from anywhere. See you there!
Ekene is a Developer Experience Engineer and Technical Writer. He is currently working with the Developer Experience team at Netlify where they build tools, create content, open-source repos, and demos to teach and also help developers build a better web with Netlify's products and services.