Strapi blog logo
  • Product

      Why Strapi?Content ArchitectureRoadmapIntegrationsTry live demo
      OverviewContent Types BuilderCustomizable APIMedia LibraryRoles & Permissions
      Discover Strapi Enterprise EditionDiscover our partners
  • Pricing

  • Solutions

      Static WebsitesMobile ApplicationsCorporate websitesEditorial SitesEcommerce
      Delivery HeroL'EquipeSociete GeneralePixelDustBanco International
      Discover all our user stories
  • Community

      CommunityWrite for the communityWall of LoveStrapi Conf 2021
      SlackGitHubYoutubeCommunity Forum
      Meet the Strapi Community StarsDiscover the Strapi Showcase
  • Resources

      BlogStartersNewsroomSupport
      Strapi AcademyTutorialsVideos GuidesWebinars
      The Guide to Headless CMS Strapi Community Forum
  • Docs

      Getting StartedContent APIConfigurationInstallationDeploymentMigration
      Getting StartedContent ManagerContent-Types BuilderUsers, Roles & PermissionsPlugins
      Developer DocumentationStrapi User Guide

Looking for our logo ?

Logo Brand download
Download Logo Pack
See more Strapi assets
Strapi blog logo
  • Product

    Product

    • Why Strapi?
    • Content Architecture
    • Roadmap
    • Integrations
    • Try live demo

    Features

    • Overview
    • Content Types Builder
    • Customizable API
    • Media Library
    • Roles & Permissions
    • Discover Strapi Enterprise Edition
    • Discover our partners
    Features cover

    Unlock the full potential of content management

    See all features
    Strapi Enterprise Edition

    Discover the advanced features included in Strapi Enterprise Edition.

    Get Started
  • Pricing
  • Solutions

    Solutions

    • Static Websites
    • Mobile Applications
    • Corporate websites
    • Editorial Sites
    • Ecommerce

    Stories

    • Delivery Hero
    • L'Equipe
    • Societe Generale
    • PixelDust
    • Banco International
    • Discover all our user stories
    Delivery Hero team

    Delivery Hero manages their partner portal with Strapi.

    Read their story
    turn 10 studios website

    How 1minus1 delivered a creative website for Turn10 Studios 25% faster with Strapi

    Discover their story
  • Community

    Community

    • Community
    • Write for the community
    • Wall of Love
    • Strapi Conf 2021

    Resources

    • Slack
    • GitHub
    • Youtube
    • Community Forum
    • Meet the Strapi Community Stars
    • Discover the Strapi Showcase
    Strapi Conf

    The first Strapi Global User Conference.

    Register now
    Write for the community

    Contribute on educational content for the community

    Discover the program
  • Resources

    Resources

    • Blog
    • Starters
    • Newsroom
    • Support

    Learning

    • Strapi Academy
    • Tutorials
    • Videos Guides
    • Webinars
    • The Guide to Headless CMS
    • Strapi Community Forum
    Introducing Strapi Academy

    Everything you need to know to master Strapi.

    Go to the academy
    Strapi Repository on GitHub

    Get started with the Strapi repository

    Go to repository
  • Docs

    Developers

    • Getting Started
    • Content API
    • Configuration
    • Installation
    • Deployment
    • Migration

    User Guide

    • Getting Started
    • Content Manager
    • Content-Types Builder
    • Users, Roles & Permissions
    • Plugins
    • Developer Documentation
    • Strapi User Guide
    Install Strapi

    Install Strapi locally or wherever you need.

    Get Started
    Migration Guides Strapi

    Using a previous version of Strapi? Migrate to the latest.

    Read Guides
Get Started
Back to articles

Building a Jamstack Food Ordering App with Strapi, Gridsome & Snipcart 3/6

Building a Jamstack Food Ordering App with Strapi, Gridsome & Snipcart
  • Share on facebook
  • Share on linkedin
  • Share on twitter
  • Share by email
Ekene Eze

Ekene Eze

This article is part of 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 walked through the process of setting up a Strapi application and creating products for our application. In this part, we will connect our Gridsome app with the Strapi app we created in the first part to fetch products and display for users.

Consuming products with Gridsome and GraphQL

Fetch products

The products we'll display in our Gridsome application will come from the Strapi products endpoint. Luckily for us, Gridsome makes it possible for us to fetch data from the Strapi products endpoint into the GraphQL data layer that manages the data for our Gridsome application.

To do this, we need to install Axios. Axios is a promise-based HTTP client for the browser that makes it possible for you to communicate between different services. Run the following command to install Axios:

npm i axios

With Axios installed, open the project's gridsome.server.js file and update it with the snippet below:

//gridsome.server.js
const axios = require("axios");
module.exports = function(api) {
    // whitelist vuetify for webpack code here 
  };

  api.loadSource(async (actions) => {
    const { data } = await axios.get("http://localhost:1337/products");
    const collection = actions.addCollection({
      typeName: "Product",
    });
    for (const product of data) {
      collection.addNode({
        id: product.id,
        title: product.title,
        price: product.price,
        rating: product.rating,
        description: product.description,
        image: product.image.formats.thumbnail.url,
        instructions: product.instructions,
      });
    }
  });
  api.createPages(({ createPage }) => {
    // Use the Pages API here: https://gridsome.org/docs/pages-api/
  });

Here, we are making a basic API call to fetch a list of products from our Strapi products endpoint which I'm running locally at localhost:1337/products. You can consider collection in the above snippet as an array where we'll push each individual product returned from the endpoint. Hence, collection.addNode is the equivalence of the regular array.push.

Each node contains all the details we want to get from a product, like the title, description, price etc. As a result, we can loop through the entire data returned and get the individual products as well as their respective details.

Display products

Having fetched these products from Strapi, we can display them for users to interact with on the frontend. To do that, first let's create a new src/components/Products.vue component. Within this component, we'll create the template to organize the products using Vuetify's card components. Update it with the snippet below:

// src/components/Products.vue
<template>
  <div>
    <h1
      v-if="show"
      align="center"
      justify="center"
      class="py-5 orange white--text"
    >
      {{ banner }}
    </h1>
    <v-container class="mb-3">
      <v-row :align="align" no-gutters>
        <v-col md="4" v-for="edge in $page.products.edges" :key="edge.node.id">
          <g-link
            :to="`/products/${edge.node.id}`"
            style="text-decoration: none; color: inherit"
          >
            <v-card :loading="loading" class="ma-3" shaped>
              <v-img
                height="250"
                :src="`http://localhost:1337${edge.node.image}`"
              ></v-img>
              <v-card-title>{{ edge.node.title }}</v-card-title>
              <v-card-text>
                <v-row align="center" class="mx-0">
                  <v-rating
                    :value="edge.node.rating"
                    color="amber"
                    dense
                    half-increments
                    readonly
                    size="14"
                  ></v-rating>
            
                </v-row>
                <div class="my-4 subtitle-1">$ {{ edge.node.price }}</div>
                <div>
                  {{ `${edge.node.description.slice(0, 120)}...` }}
                </div>
              </v-card-text>
              <v-card-actions>
                <v-btn
                  rounded
                  outlined
                  color="orange"
                  text
                >
                  Add to cart
                </v-btn>
              </v-card-actions>
            </v-card>
          </g-link>
        </v-col>
      </v-row>
    </v-container>
  </div>
</template>
<script>
export default {
  props: ["banner", "show"],
};
</script>

At the moment, all we've done is create a Vuetify template that will hold the product data coming from our GraphQL data layer. We have provisioned fields for product description, price, title, rating, and image. To show this component to the users, we'll have to render it in the Index page. So let's do minor updates to the index.vue file.

In the script section, import the Products component like so:

//index.vue
import Products from "@/components/Products.vue";

In the template section, just after the render the Product component like so:

//index.vue
<Products show="false" banner="Best Sellers" />

Finally to get all the products data we need to render here from our data layer, let's define a GraphQL query on our Product type:

// src/pages/index.vue
<page-query>
query{
  products: allProduct{
    edges{
      node{
        id,
        title,
        description,
        rating,
        price,
        image
      }
    }
  }
}
</page-query>

Here, we are querying for the product details from our GraphQL data layer to use in the template. In the query above, consider edges to be a regular array of products and node to be the individual product. Before we proceed, let's run this query in the GraphQL explorer and see what the result look like:

{
  "data": {
    "products": {
      "edges": [
        {
          "node": {
            "id": "7",
            "title": "Seafood",
            "description": "Seafood is any form of sea life regarded as food by humans. Seafood prominently includes fish and shellfish. Shellfish include various species of molluscs, crustaceans, and echinoderms. Historically, sea mammals such as whales and dolphins have been consumed as food, though that happens to a lesser extent in modern times",
            "price": 300,
            "rating": 5,
            "image": "/uploads/thumbnail_seafood_d3e69aad71.png"
          }
        },
        {
          "node": {
            "id": "6",
            "title": "Sandwich",
            "description": "Spread mayo, butter or cream cheese all the way to the edges of each slice of bread to create a seal against wet sandwich fillings. Also, try packing high moisture ingredients, like tomatoes, pickles, and cucumbers, separately",
            "price": 150,
            "rating": 3,
            "image": "/uploads/thumbnail_miscellaneous_e0812098cf.png"
          }
        },
        {
          "node": {
            "id": "5",
            "title": "Dessert",
            "description": "Dessert is a course that concludes a meal. The course usually consists of sweet foods, such as confections dishes or fruit, and possibly a beverage such as dessert wine or liqueur, however in the United States it may include coffee, cheeses, nuts, or other savory items regarded as a separate course elsewhere",
            "price": 100,
            "rating": 4,
            "image": "/uploads/thumbnail_dessert_4fdacb1066.png"
          }
        },
        {
          "node": {
            "id": "4",
            "title": "Lamb",
            "description": "Lamb, hogget, and mutton are the meat of domestic sheep (species Ovis aries) at different ages. A sheep in its first year is called a lamb, and its meat is also called lamb",
            "price": 250,
            "rating": 3,
            "image": "/uploads/thumbnail_lamb_8f452bb9a3.png"
          }
        },
        {
          "node": {
            "id": "3",
            "title": "Chicken wings",
            "description": "Chicken is a type of domesticated fowl, a subspecies of the red junglefowl. It is one of the most common and widespread domestic animals",
            "price": 400,
            "rating": 3,
            "image": "/uploads/thumbnail_chicken_c6742f8df3.png"
          }
        },
        {
          "node": {
            "id": "2",
            "title": "Homemade pasta",
            "description": "Pasta is a staple food of traditional Italian cuisine, with the first reference dating to 1154 in Sicily. Humans have been eating beef since prehistoric times",
            "price": 400,
            "rating": 5,
            "image": "/uploads/thumbnail_pasta_1e163eb9f7.png"
          }
        },
        {
          "node": {
            "id": "1",
            "title": "Grilled Beef",
            "description": "Beef is the culinary name for meat from cattle, particularly skeletal muscle. Humans have been eating beef since prehistoric times. Beef is a source of high-quality protein and essential nutrients. Check below for preparation instructions",
            "price": 300,
            "rating": 4,
            "image": "/uploads/thumbnail_beef_b95f539dc8.png"
          }
        }
      ]
    }
  }
}

At this point, if you save all the updates made to the index.vue file, we should get an updated view on the browser at localhost:8080:

At the moment, we've achieved our goal of rendering the products from our Strapi application on the Gridsome frontend app.

You might have noticed that when you click on any of the products, it opens a new route http://localhost:8080/products/{id} which represents the single page route for that particular product. This is possible because we wrapped each individual product card in a <g-link> tag which basically provides client-side routing capabilities to our Gridsome application:

<g-link
    :to="`/products/${edge.node.id}`"
    style="text-decoration: none; color: inherit"
> 
// product card here
</g-link>

Conclusion

So quick recap. In this part, we've consumed the product endpoint we created with Strapi in the first part of this series. Gridsome's GraphQL data layer was instrumental in this process as we have demonstrated. It made it easy to access the data we need wherever we need. We also got our hands dirty with Vuetify, creating components and styling the product cards was equally just as fun. In the next part, we'll look at how we can display product details in a single product view page where customers can place orders.

  • Share on facebook
  • Share on linkedin
  • Share on twitter
  • Share by email

You might also be interested in...

Announcing StrapiConf - Our First Global User Conference
  • Strapi
  • Announcement

Announcing StrapiConf - Our First Global User Conference

Announcing the first Strapi global user conference! It's a one day conference for the Strapi Community to learn, contribute, and collaborate on the future of the leading open source Headless CMS.

Victor Coisne

Victor Coisne

November 12, 2020

Strapi Online Meetup #8 Recap
  • Online Meetup

Strapi Online Meetup #8 Recap

This is the recap of the online meetup hosted by Daniel and Chris Sevilleja from Digital Ocean showcasing how to build and deploy web apps to the Digital Ocean App Platform.

Daniel Madalitso Phiri

Daniel Madalitso Phiri

November 30, 2020

Building a Jamstack Food Ordering App with Strapi, Gridsome & Snipcart 4/6
  • Guides & Tutorials

Building a Jamstack Food Ordering App with Strapi, Gridsome & Snipcart 4/6

Learn how to create a food ordering app with Gridsome, Snipcart and your favorite headless CMS: Strapi

Ekene Eze

Ekene Eze

December 7, 2020

Unleash content.

Read the docs
Get Started

Strapi is the most popular open-source Headless CMS. Strapi gives developers the freedom to use their favorite tools and frameworks while allowing editors to easily manage their content and distribute it anywhere.

Product

  • Why Strapi?
  • Content Architecture
  • Features
  • Enterprise Edition
  • Partner Program
  • Roadmap
  • Support
  • Integrations
  • Try live demo

Resources

  • How to get started
  • Meet the community
  • Tutorials
  • API documentation
  • GitHub repository
  • Starters
  • Strapi vs Wordpress
  • The Guide to headless CMS

Integrations

  • Gatsby CMS
  • React CMS
  • Vue.js CMS
  • Nuxt.js CMS
  • Next.js CMS
  • Angular CMS
  • Gridsome CMS
  • Jekyll CMS
  • 11ty CMS
  • Svelte CMS
  • Sapper CMS
  • Ruby CMS
  • Python CMS

Company

  • About us
  • Blog
  • Careers
  • Contact
  • Newsroom
  • ยฉ 2021, Strapi
  • LicenseTermsPrivacy