Updated April 2023 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 here
Screenshots of final product:
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:
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 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 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.
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).
mkdir next-food-delivery
next-food-delivery
folder in your favourite code editor, VS Code preferably and run the following code in the integrated terminal. npx create-next-app@latest frontend
You should see the following output.
➜ npx create-next-app@latest frontend
Need to install the following packages:
create-next-app@13.3.4
Ok to proceed? (y) y
Here are the options I selected for this tutorial, make sure you chose the same ones to follow along:
➜ next-food-delivery npx create-frontend frontend
Need to install the following packages:
create-next-app@13.3.4
Ok to proceed? (y) y
✔ Would you like to use TypeScript with this project? … No
✔ Would you like to use ESLint with this project? … Yes
✔ Would you like to use `src/` directory with this project? … No
✔ Would you like to use experimental `app/` directory with this project? … No
✔ What import alias would you like configured? … @/*
Creating a new Next.js app
The following code will create a folder named frontend
and set up NextJS.
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.
cd frontend
touch .env.development
Inside /.env.development
development file add the following code:
NEXT_PUBLIC_API_URL='http://localhost:1337'
This tutorial makes use of Next And Tailwind to implement Tailwind into the application.
Tailwind is a front-end library to easily style your application. This will take care of the heavy lifting on the front end.
Open your terminal in the frontend
directory and run the following command:
Note: if you selected to use tailwind in the previous option you can omit this step.
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Configure your template paths
Add the following code inside the tailwind.config.js
file.
1/** @type {import('tailwindcss').Config} */
2module.exports = {
3 content: [
4 "./app/**/*.{js,ts,jsx,tsx}",
5 "./pages/**/*.{js,ts,jsx,tsx}",
6 "./components/**/*.{js,ts,jsx,tsx}",
7 ],
8 theme: {
9 extend: {},
10 },
11 plugins: [],
12};
Add the Tailwind directives to your CSS
Add the @tailwind directives by replacing your css inside the styles/globals.css
file with the following.
1@tailwind base;
2@tailwind components;
3@tailwind utilities;
If the above was created for you automatically, you can remove all of the other css after the @tailwind directives.
We are importing our CSS in the _app.js
file inside the pages directory . This will allow us to share our CSS and and Layout component across all pages.
You can read more about the
_app.js
handling here
_app.js
to see where we are importing our CSS.Path: /frontend/pages/_app.js
1import "@/styles/globals.css";
2
3export default function App({ Component, pageProps }) {
4 return <Component {...pageProps} />;
5}
Path: frontend/pages/index.js
1import Head from "next/head";
2
3export default function Home() {
4 return (
5 <>
6 <Head>
7 <title>Create Next App</title>
8 <meta name="description" content="Generated by create next app" />
9 <meta name="viewport" content="width=device-width, initial-scale=1" />
10 <link rel="icon" href="/favicon.ico" />
11 </Head>
12 <main className="mx-auto container">
13 <button className="inline-block py-3 px-7 w-full md:w-auto text-lg leading-7 text-green-50 bg-green-500 hover:bg-green-600 font-medium text-center focus:ring-2 focus:ring-green-500 focus:ring-opacity-50 border border-transparent rounded-md shadow-sm">
14 Primary button
15 </button>
16 </main>
17 </>
18 );
19}
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.
Designing the page Now that we have Tailwind running inside of our Next project, we can style the shared frontend components like the nav bar.
Add the following code bellow:
Path: /frontend/components/Layout.js
1import Head from "next/head";
2import Link from "next/link";
3
4function Navigation() {
5 return (
6 <nav className="container mx-auto flex justify-between p-6 px-4">
7 <div className="flex justify-between items-center w-full">
8 <div className="xl:w-1/3">
9 <Link
10 className="block text-lg max-w-max ext-coolGray-500 hover:text-coolGray-900 font-medium"
11 href="/"
12 >
13 Food Order App
14 </Link>
15 </div>
16
17 <div className="xl:block xl:w-1/3">
18 <div className="flex items-center justify-end">
19 <Link
20 className="text-coolGray-500 hover:text-coolGray-900 font-medium"
21 href="/"
22 >
23 Home
24 </Link>
25 <Link
26 className="inline-block py-2 px-4 mr-2 leading-5 text-coolGray-500 hover:text-coolGray-900 bg-transparent font-medium rounded-md"
27 href="/login"
28 >
29 Log In
30 </Link>
31 <Link
32 className="inline-block py-2 px-4 text-sm leading-5 text-green-50 bg-green-500 hover:bg-green-600 font-medium focus:ring-2 focus:ring-green-500 focus:ring-opacity-50 rounded-md"
33 href="/register"
34 >
35 Sign Up
36 </Link>
37 </div>
38 </div>
39 </div>
40 </nav>
41 );
42}
43
44export default function Layout(props) {
45 const title = "Welcome to Nextjs";
46
47 return (
48 <div>
49 <Head>
50 <title>{title}</title>
51 <meta charSet="utf-8" />
52 <meta name="viewport" content="initial-scale=1.0, width=device-width" />
53 </Head>
54 <Navigation />
55 <div className="container mx-auto px-4">{props.children}</div>
56 </div>
57 );
58}
_app.js
file to use the new Layout component across the application:Path: /frontend/frontend/pages/_app.js
1import "@/styles/globals.css";
2import Layout from "@/components/Layout";
3
4export default function App({ Component, pageProps }) {
5 return (
6 <Layout>
7 <Component {...pageProps} />
8 </Layout>
9 );
10}
You should now have a shared header bar across all your pages, as shown in the output below:
Path: /frontend/pages/register.js
1/* pages/register.js */
2export default function RegisterRoute() {
3 return <h1>Sign Up</h1>;
4}
Path: /frontend/pages/login.js
1/* pages/login.js */
2
3export default function LoginRoute() {
4 return <h1>Log In</h1>;
5}
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.
This tutorial uses Windows 10 as its operating system.
PgAdmin is installed when you install PostgreSQL.
When PgAdmin opens, you will be prompted to put in the password entered during the installation as shown below.
On the left navigation bar, click on Servers and click on PostgreSQL 14.
Right-click on Databases, hover over Create and click on Database.
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.
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:
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
next-food-delivery
's directory and run the following code to create a Strapi application. npx create-strapi-app@latest backend
Here are my options:
➜ next-food-delivery npx create-strapi-app@latest backend
? Choose your installation type Custom (manual settings)
? Choose your preferred language JavaScript
? Choose your default database client postgres
? Database name: nextapp
? Host: 127.0.0.1
? Port: 5432
? Username: postgres
? Password: ***********
? Enable SSL connection: No
Creating a project with custom database options.
Available commands in your project:
yarn develop
Start Strapi in watch mode. (Changes in Strapi project files will trigger a server restart)
yarn start
Start Strapi without watch mode.
yarn build
Build Strapi admin panel.
yarn strapi
Display all available commands.
You can start by doing:
You can start your project by running the following command:
cd backend
npm run develop
You should see the following code that was automatically setup for you when we created your Strapi project with your postgres credentials.
1//
2 postgres: {
3 connection: {
4 connectionString: env('DATABASE_URL'),
5 host: env('DATABASE_HOST', 'localhost'),
6 port: env.int('DATABASE_PORT', 5432),
7 database: env('DATABASE_NAME', 'strapi'),
8 user: env('DATABASE_USERNAME', 'strapi'),
9 password: env('DATABASE_PASSWORD', 'strapi'),
10 ssl: env.bool('DATABASE_SSL', false) && {
11 key: env('DATABASE_SSL_KEY', undefined),
12 cert: env('DATABASE_SSL_CERT', undefined),
13 ca: env('DATABASE_SSL_CA', undefined),
14 capath: env('DATABASE_SSL_CAPATH', undefined),
15 cipher: env('DATABASE_SSL_CIPHER', undefined),
16 rejectUnauthorized: env.bool(
17 'DATABASE_SSL_REJECT_UNAUTHORIZED',
18 true
19 ),
20 },
21 schema: env('DATABASE_SCHEMA', 'public'),
22 },
23 pool: { min: env.int('DATABASE_POOL_MIN', 2), max: env.int('DATABASE_POOL_MAX', 10) },
24 },
25//
You can find your database variables within your .env file.
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.
Ryan is an active member of the Strapi community and he's been contributing at a very early stage by writing awesome tutorial series to help fellow Strapier grow and learn.