Creating a Full Stack Udemy Clone Project with Next.js

Creating a Full Stack Udemy Clone Project with Next.js

In this article, we will walk through building a full-stack Udemy clone application with Next.js for the front end, MongoDB for the database, and Node.js/Express for the API. By the end, we will have a working course marketplace with user authentication, shopping cart functionality, course purchases, and deployment.

What is Udemy Marketplace?

Udemy is one of the largest online learning marketplaces in the world, with over 50 million students taking courses on a wide range of subjects from business to programming to personal development.

On Udemy, individual instructors can create and sell online video courses covering their areas of expertise. Courses typically include pre-recorded video lectures, slides, code examples, assignments, and quizzes.

Why build a full stack clone with Next.js?

There are a few key reasons it makes sense to build a Udemy clone project as a full-stack application using Next.js:

  • Next.js simplifies building server-rendered React apps, which is important for SEO and performance on a site like this with dynamic course data.

  • Having both the front end and backend developed together in a single codebase allows for tighter integration between the two and streamlines the development process.

  • Next.js generates HTML at build time so the frontend loading experience is very fast. This provides a smooth user experience when browsing courses.

  • Next.js routing and API integration makes it easy to fetch course data server-side when pages are rendered. This reduces the need for separate frontend/backend projects.

  • Next.js simplicity supports rapid iteration and deployment. New features can be deployed easily without making major changes to the underlying architecture.

  • Building the full-stack ourselves gives full control over the application and makes it easy to extend with things like payments, user accounts, etc. versus relying on other platforms.

Project Setup

The first step is to decide on our tech stack. For this project, we will use:

  • Next.js for the frontend - Next.js is a React framework that makes building full-stack applications easy with features like server-side rendering and automatic code splitting.

  • MongoDB as our database - MongoDB is a popular document-oriented NoSQL database that will allow us to store courses, users, orders, and other data in flexible document structures.

  • Node.js and Express for the API backend - We'll build a REST API with Express to handle data requests from the frontend like fetching courses, authentication, purchases, etc.

With our stack selected, let's set up the basic project structure:

udemy-clone/
  frontend/ 
    pages/
    components/
    styles/
    api/
  backend/
    models/ 
    routes/
    server.js
  db/

Inside the frontend directory, run npx create-next-app to initialize a new Next.js project. Then in backend, run npm init to create a new Node project.

Next, we'll need to design some basic data models for MongoDB to store our data. Here are examples of models we might need:

Course {
  title: String,
  description: String, 
  lessons: [Lesson],
  price: Number,
  //etc
}

Lesson {
  title: String,
  content: String  
}

User {
  name: String,
  email: String, 
  password: String,
  cart: [CartItem],
  purchased: [Course]  
}

CartItem {
  course: ObjectId, 
  quantity: Number
}

Order {
  user: ObjectId,
  items: [CartItem],
  purchaseDate: Date
}

Now our project is set up with the basic structure and data models we need!

Frontend Development

Let's start building out the frontend pages. We'll begin with a Landing page to display featured courses:

// pages/index.js

export default function Home() {

  const [courses, setCourses] = useState([])

  useEffect(() => {
    // fetch featured courses from API
    fetchCourses()
  }, [])

  async function fetchCourses() {
    const res = await fetch('/api/courses')
    setCourses(res.data) 
  }

  return (
    <Layout>
      <Hero />

      <CoursesList courses={courses} />

      <Footer />
    </Layout>
  )
}

Some key components we include:

  • Layout wrapper for consistent page structure

  • Hero banner section

  • CoursesList to display courses fetched from API

  • Footer shared footer

Now let's build out the Course Detail page to view a specific course:

// pages/courses/[slug].js

export default function Course({course}) {

  return (
    <Layout>
      <Breadcrumbs category={course.category} />

      <CourseHero 
        image={course.image}
        title={course.title} 
      />

      <CourseDetails course={course}>

      <AddCartButton course={course} />

      <LessonsList lessons={course.lessons}/>

      <Footer />
    </Layout>
  )
}

export async function getServerSideProps({params}) {

  const res = await fetch(`/api/courses/${params.slug}`)
  const course = await res.json()

  return {
    props: {
      course
    }
  }

}

And we render the course content passed via SSR.

Next we'll build the Cart, Checkout, and User dashboard pages. Some key pieces:

  • Display cart items and totals

  • Collect payment information at checkout

  • Save orders to the database

  • Connect to Stripe for payments

  • Show user profile/purchases

With our core pages created, the front end is taking shape! Now it's time to connect it to our backend API.

Backend Development

First, install dependencies:

npm install express mongodb cors body-parser

In server.js:

const express = require('express');
const mongoose = require('mongodb');
const cors = require('cors');

const app = express();

app.use(cors());
app.use(express.json()); 

// Connect to MongoDB
mongoose.connect(MONGO_URL)

Then we'll create some sample routes:

// Get all courses
app.get('/api/courses', async (req, res) => {
  const courses = await Course.find()
  res.send(courses)
})

// Get single course 
app.get('/api/courses/:id', async (req, res) => {
  const course = await Course.findById(req.params.id)
  res.send(course)
})

// Add course to cart
app.post('/api/cart', async (req, res) => {
  // Save to database
  res.send({message: 'Added to cart!'})
})

Continue building out CRUD routes for courses, users, orders etc. We also need authentication routes:

// Register user
app.post('/api/users/register', async (req, res) => {
  // Validate & save user
  const token = createJWT(user)
  res.send({token}) 
})

// Login user 
app.post('/api/users/login', async (req, res) => {
  // Validate credentials
  const token = createJWT(user)
  res.send({token})
})

Our API is ready! Deploy it to Heroku so our frontend can consume it.

Purchasing Integration

Now for one of the most important parts - payments! Let's integrate with Stripe to enable credit card purchases.

First, sign up for a Stripe account and get your publishable and secret keys. Then:

// server.js

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY)

app.post('/api/checkout', async (req, res) => {

  const session = await stripe.checkout.sessions.create({
    // Create checkout session
  })

  res.json({ 
    sessionId: session.id
  })

})

On the frontend Checkout page:

// checkout.js

const stripe = Stripe(process.env.STRIPE_PUBLISHABLE_KEY)

async function handleSubmit() {

  // Call backend to create Checkout Session
  const { session } = await fetch('/api/checkout')  

  // Redirect to Checkout
  const { error } = await stripe.redirectToCheckout({
    // Checkout props  
  })

  if (error) {
    console.warn(error)
  }

}

This will open the Stripe checkout modal. On successful payment, the Order can be saved to the database and access to courses granted.

And with that, purchases are integrated!

Deployment

Finally, let's deploy our fullstack app so it's live on the web!

We've already deployed the API to Heroku. For the frontend:

  1. Build the Next.js production build:

  2.   npm run build
    
  3. Install and initialize Vercel:

     npm install -g vercel
     vercel
    
  4. Link the github repository and deploy

Vercel will detect the build outputs and deploy the production site. Now users can visit your site and browse, purchase and learn from courses!

Final Thoughts

This article guides through building a full stack Udemy clone using Next.js, MongoDB, Node/Express featuring course catalogs, payments with Stripe, user auth, and deployment to Vercel and Heroku for hands-on full stack dev experience.