DEV Community

Cover image for Next.js Full Stack Food Delivery App (5+ Hours Free Tutorial)
Safak
Safak

Posted on

Next.js Full Stack Food Delivery App (5+ Hours Free Tutorial)

Hey, fellow developers!

I'm a full-stack web developer with a passion for sharing my web development journey with other devs. Recently, I’ve created a full stack Restaurant application where users can order food. Feel free to check it out on my GitHub page.

Moreover, I’ve published the tutorial of the project on my Youtube channel. You can reach the playlist here

Whether you're a seasoned developer or a curious learner, this tutorial series has something for everyone.


What technologies are used?

Backend:

Next.js App Router (API)

Database:

PostgreSQL (but you can choose any other database provider because we'll be using Prisma ORM)

Auth:

Auth.js (Next-Auth) with Prisma Adapter

Payment Gateway:

Stripe Custom Payments

Front-End Framework:

Next.js App Router (Pages)

UI libraries:

Tailwind CSS

State Management Library:

Zustand

File Storage:

Cloudinary


Design Part of the Restaurant App


In this part, we’ll design the application using reusable React components and Tailwind CSS. It’s a great tutorial to understand the difference between Next.js server-side components and client-side components. You’ll also learn how to design a fully responsive app using Tailwind classes.

The design consists of seven pages and ten components.

  • src
    • app
      • page.tsx (Homepage)
      • cart
        • page.tsx
      • login
        • page.tsx
      • menu
        • page.tsx
        • [categoryId]
          • page.tsx
      • orders
        • page.tsx
      • product
        • [id]
          • page.tsx
    • components
      • CartIcon.tsx
      • CountDown.tsx
      • Featured.tsx
      • Footer.tsx
      • Navbar.tsx
      • Menu.tsx
      • Notification.tsx
      • Offer.tsx
      • Price.tsx
      • Slider.tsx

Full Stack Part of the Food Ordering App


In this part, we’ll create the API route and communicate with the front end. I preferred PostgreSQL, but as I mentioned above, you can use any other database because we won’t write a single line of SQL code thanks to Prisma. We’ll make all the CRUD operations using Prisma Client easily.

  • src
    • app
      • api
        • create-intent
          • route.ts
        • confirm
          • route.ts
        • categories
          • route.ts
        • orders
          • route.ts
        • products
          • route.ts
        • auth -[…nextAuth]
          • route.ts
    • docker
      • docker-compose.yml
    • utils
      • auth.ts
      • connect.ts
      • store.ts

For the authentication, we’ll be using Next-Auth Prisma Adapter and it’ll handle all the auth process including sessions, user accounts, tokens, role based authorizations etc.

To do that, you need to create a schema file in prisma/schema.prisma similar to this one:

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
  shadowDatabaseUrl = env("SHADOW_DATABASE_URL") // Only needed when using a cloud provider that doesn't support the creation of new databases, like Heroku. Learn more: https://pris.ly/d/migrate-shadow
}

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["referentialActions"] // You won't need this in Prisma 3.X or higher.
}

model Account {
  id                 String  @id @default(cuid())
  userId             String
  type               String
  provider           String
  providerAccountId  String
  refresh_token      String?  @db.Text
  access_token       String?  @db.Text
  expires_at         Int?
  token_type         String?
  scope              String?
  id_token           String?  @db.Text
  session_state      String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
}

model Session {
  id           String   @id @default(cuid())
  sessionToken String   @unique
  userId       String
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model User {
  id            String    @id @default(cuid())
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  isAdmin       Boolean   @default(false)
  image         String?
  accounts      Account[]
  sessions      Session[]
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
}
Enter fullscreen mode Exit fullscreen mode

We use this standard schema for the Prisma adapter; you can find it in the official documentation.

I’ve only added the isAdmin field in the user model to give a role for users. I use a boolean because my application has only two roles (admin/regular user).

Source:

Role-Based Authentication with Next.js and Prisma

After completing the authentication and CRUD operations, we’ll start adding the cart functionality. In the project, Zustand was my preference for state management.

If you prefer a simple and concise state management solution, Zustand might be a better fit.

Creating a Zustand store is as simple as calling a single function, passing a function that defines the store’s initial state and actions.

Source:

Learn more about Zustand

And finally, we’ll implement Stripe custom payments with the shipping option, and users will be able to create new orders and complete the payment process.

I hope it was useful. If you want to learn more about web development and practice with real-world projects, you can check out my channel and other posts.

Other Dev.to Posts

🎥 Full Stack Youtube Clone (5 hours free tutorial)
🛍️ Full Stack E-Commerce App (+8 Hours free tutorial)
📺 Full Stack Netflix App (+7 Hours free tutorial)
🧑‍🤝‍🧑 Full Stack Social Media App (+7 Hours free tutorial)

Lama Dev

🔥 Lama Dev YouTube Channel
⚡️ Lama Dev Instagram
👾 Source Code

Top comments (1)

Collapse
 
Sloan, the sloth mascot
Comment deleted