Create a Food Ordering App with Strapi and Next.js 1/7

Create a Food Ordering App with Strapi and Next.js 1/7

Learn how to create a food ordering app with Strapi and Next.js using React Hooks.

Tutorial updated by Fredrick Emmanuel and Paul Bratslavsky

This tutorial will walk you through how to use Next.js to power your UI, complete using GraphQL, Stripe, Strapi, and Next to developing a full-stack application complete with the powerful Strapi (Headless CMS) powering the backend.

Get ready to develop an online food ordering app, more info on the tech stack here: Next.js, GraphQL, Stripe and Strapi! From sign up to order, you are going to let users discover restaurants, dishes and order meals.

Your app will be complete with user login, registration, authentication, image upload, restaurant creation, dish creation, cart functionality, and stripe order integration. The demo of the final result should make you hungry:

Note: The source code is available on GitHub for Frontend and Backend.

Screenshots of the final product:

Strapi

Strapi is the most advanced open-source Node.js Headless Content Management System used to build scalable, secure, production-ready APIs quickly and efficiently saving developers countless hours of development. With its extensible plugin system, it provides an enormous set of built-in features: Admin Panel, Authentication & Permissions management, Content Management, API Generator, etc. Strapi is 100% open-source, which means:

  • Strapi is completely free.

  • You can host it on your servers, so you own the data.

  • It is entirely customizable and extensible, thanks to the plugin system.

Next.js

Next is a lightweight React framework to create server-rendered applications. Next.js will take care of the heavy lifting of the application build such as code splitting, HMR (hot module replacement) SSR (server-side rendering) and allow us to focus on writing the code, not our build config.

GraphQL

GraphQL is a query language also developed by Facebook to allow the front end of an application to easily query an application’s API. Each query requests only the data needed to be rendered by the current view. This allows the developer to craft a great user experience across multiple devices and screen sizes.

Stripe

Stripe is one payment processor for applications today. Stripe has developed the tools and SDKs to allow developers to craft and integrate secure, compliant payment processing into any app with ease.

Table of contents

🏗️ Setup

Next

To set up Next.js you will need an empty directory to install the dependencies and host our project root. This project will be split into two parts, one for the front end (Next.js code) and one for the backend (Strapi code).

  1. Run the code below in your terminal to create this project’s source folder.
mkdir next-react-hooks-strapi-food-delivery
  1. Next, Open the next-react-hooks-strapi-food-delivery folder in your favourite code editor, VS Code preferably and run the following code in the integrated terminal.

  2. The following code will create a folder named frontend and set up NextJS.

mkdir Frontend
    cd Frontend
    npx create-next-app next-app

Setting up the NextJS application for the first time will require you to install the create-next-app package, as shown in the output below.

Create-next-app install

You should get a similar output to the one shown below.

Next-app created successfully

First things first, let’s set up our environment variables to avoid hard coding the API URL and having to update it on every deployment. Create a new file in the project’s directory and add the following code.

touch .env.development

Path: /env.development

NEXT_PUBLIC_API_URL='http://localhost:1337'

Adding Bootstrap

This tutorial makes use of react-strap to implement Bootstrap into the application. React-strap is a front-end library to easily create Bootstrap components and styling. This will take care of the heavy lifting on the front end. Open your terminal in the next-app directory and run the install reactstrap command below:

npm install reactstrap

To import the CSS and share a Layout component across all pages, use the _app.js file inside the pages directory.

The _app.js file inside the pages directory will override the default App.js used by Next and be rendered on each page, allowing us to set and manage global styles and shared components in one place of the application.

You can read more about the _app.js handling here

  1. Open the pages folder, select the _app.js and add the following code

Path: /frontend/next-app/pages/_app.js

/* _app.js */
    import React from "react";
    import App from "next/app";
    import Head from "next/head";

    export default class MyApp extends App {
      render() {
        const { Component, pageProps } = this.props;
        return (
          <>
            <Head>
              <link
                rel="stylesheet"
                href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
                integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
                crossOrigin="anonymous"
              />
            </Head>

            <Component {...pageProps} />
          </>
        );
      }
    }
  1. Now add the following code inside the index.js file to insert reactstrap components.

Path: /frontend/next-app/pages/index.js

/* pages/index.js */
    import { Button, Alert } from "reactstrap";

    export default () => {  
      return (
        <div>
          <div>
            <Alert color="primary">
              Hello Project is strapi-next with Bootstrap
            </Alert>
            &nbsp; <Button color="primary">Hello from nextjs</Button>
          </div>
        </div>
      );
    };
  1. Next, open your terminal in the next-app directory and start the next application by running the command below.
npm run dev

Open this URL, localhost:3000, in your favourite browser to view the next app. You should get an output similar to the one below.

Homepage

Designing the page Now that we have Bootstrap running inside of our Next project, we can style the shared frontend components like the nav bar.

  1. Create a folder in the next-app directory named components to store all the components for the next application and create a file named Layout.js.

Next uses the <Link> component to perform the client-side routing between pages. The Link component is the next component and can accept any HTML element that has an onClick handler as a child component (<a>,<button>,<div> etc.). To style our navbar, we can use the built-in CSS in JS syntax <style jsx> shipped by default with next. Inserting CSS in JS as in next is as easy as:

<style jsx> {`
      a { color: yellow }
    `}
    </style>

This allows us to scope CSS to the components the style tag is in. You can also pass in the global option to set a global style across the project: <style jsx global> this would set styling across pages and components for all elements that match the CSS selector. You can read more on CSS in JS in the Next documents here.

  1. Open the Layout.js file and create the shared layout components and insert the Stripe script (for later):

Path: /frontend/next-app/components/Layout.js

/* /components/Layout.js */

    import React from "react";
    import Head from "next/head";
    import Link from "next/link";

    import { Container, Nav, NavItem } from "reactstrap";

    export default function Layout(props) {
      const title = "Welcome to Nextjs";
      return (
        <div>
          <Head>
            <title>{title}</title>
            <meta charSet="utf-8" />
            <meta name="viewport" content="initial-scale=1.0, width=device-width" />
            <link
              rel="stylesheet"
              href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
              integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
              crossOrigin="anonymous"
            />
            <script src="https://js.stripe.com/v3" async/>
          </Head>
          <header>
            <style jsx>
              {`
                a {
                  color: white;
                }
              `}
            </style>
            <Nav className="navbar navbar-dark bg-dark">
              <NavItem>
                <Link href="/">
                  <a className="navbar-brand">Home</a>
                </Link>
              </NavItem>

              <NavItem className="ml-auto">
                <Link href="/login">
                  <a className="nav-link">Sign In</a>
                </Link>
              </NavItem>

              <NavItem>
                <Link href="/register">
                  <a className="nav-link"> Sign Up</a>
                </Link>
              </NavItem>
            </Nav>
          </header>
          <Container>{props.children}</Container>
        </div>
      );
    }
  1. Edit the _app.js file to use the new Layout component across the application:

Path: /frontend/next-app/pages/_app.js

/* _app.js */
    import React from "react";
    import App from "next/app";
    import Head from "next/head";
    import Layout from "../components/Layout";
    export default class MyApp extends App {
      render() {
        const { Component, pageProps } = this.props;
        return (
          <>
            <Head>
              <link
                rel="stylesheet"
                href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
                integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
                crossOrigin="anonymous"
              />
            </Head>
            <Layout>
              <Component {...pageProps} />
            </Layout>
          </>
        );
      }
    }

You should now have a shared header bar across all your pages, as shown in the output below:

Homepage with the nav bar

Creating the Login and Sign up page

  1. Create two additional pages in the pages folder to allow users to sign in and sign up named login.js and register.js, respectively.

  2. Populate the files with the following code.

Path: /frontend/next-app/pages/register.js

/* pages/register.js */

    export default () => {
      return <h1>Sign Up</h1>;
    };

Path: /frontend/next-app/pages/login.js

/* pages/login.js */

    export default () => {
      return <h1>Sign In</h1>;
    };

You should now see the routes at http://localhost:3000/login and http://localhost:3000/register

Setting up the database

This tutorial uses PostgreSQL as the database for this application.

  1. Head on to the download page for PostgreSQL and follow the prompts to install PostgreSQL on your local machine.

This tutorial uses Windows 10 as its operating system.

  1. Search and open up PgAdmin in the start menu of your computer. PgAdmin will help create and manage your Strapi database.

PgAdmin is installed when you install PostgreSQL.

  1. When PgAdmin opens, you will be prompted to put in the password entered during the installation as shown below.

PyAdmin Screenshot

  1. On the left navigation bar, click on Servers and click on PostgreSQL 14.

A Sample Screenshot

  1. Right-click on Databases, hover over Create and click on Database.

A Sample Screenshot

  1. You can name the database anything you desire, but, in this tutorial, the name of the database is nextapp. Once you’re done naming the database, hit save.

nextapp database

The name of the database, nextapp, will be shown on the left navigation bar. Clicking on it will prompt a drop-down as shown below:

Install Strapi

Having a frontend is good, but your app needs a backend to manage users, restaurants, dishes and orders. To make the magic happen, let’s create a Strapi API.

Please use version >=Node 9 and have PostgreSQL installed and running on your machine.

Create Strapi server

  1. Create a folder called backend in the project’s directory.

  2. Open your terminal in the backend's directory and run the following code to create a Strapi application.

npx create-strapi-app strapiapp --quickstart
  1. Running the above command for the first time will prompt you to install Strapi, as shown in the output below. Click y and hit enter to continue with the installation.

create-strapi-app installation

  1. The quickstart option automatically builds the admin panel and runs Strapi in development mode. To start the Strapi in development mode, open your terminal in the strapiapp directory and run the command.
npm run develop
  1. Once the installation is complete, you should be redirected to http://localhost:1337/admin/auth/register-admin to create your first admin user.

Admin sign up

  1. As shown in the output below, Strapi wants to know a bit about you. You can choose to answer or decide to skip this question.

  1. Open the Backend folder, click on strapiapp, and select database.js from the config folder as shown below.

database.js

  1. Replace the following code into the database.js file to configure the PostgreSQL database.
module.exports = ({ env }) => ({
          connection: {
            client: "postgres",
            connection: {
              host: env("DATABASE_HOST", "127.0.0.1"),
              port: env.int("DATABASE_PORT", 5432),
              database: env("DATABASE_NAME", "nextapp"),//Name of database
              user: env("DATABASE_USERNAME", "postgres"),//Default username
              password: env("DATABASE_PASSWORD", "12345678"),//Password to your PostgreSQL database
              ssl: env.bool("DATABASE_SSL", false),
            },
          },
        });

Good job, you successfully set up both Next.js and Strapi projects! 🎉

🏠 In the next section, you will learn how to display the list of restaurants: https://strapi.io/blog/nextjs-react-hooks-strapi-restaurants-2.