Skip to content

Repository files navigation

Tech with Phantom β€” Modern Online Course Platform

A full-stack LMS (Learning Management System) built with Next.js 16 App Router, Auth.js v5, Prisma 7, and Neon Postgres. Designed for course creators who want a clean, production-ready starter to scale and manage their digital education business.

Live demo: https://techwithphantom.vercel.app/

Table of Contents


πŸ“‹ Overview

Tech with Phantom is a full-stack LMS platform that includes:

  • A public landing page for marketing and course promotion
  • A course directory with search and category filtering
  • Course curriculum pages with lesson lists and free preview lessons
  • An LMS viewer for authenticated learners
  • Auth system with Email/Password and Google OAuth
  • A learner dashboard with profile, orders, memberships, and settings pages

πŸ“Έ Screenshots

Landing Page

Landing Page The modern, responsive landing page showcasing the platform with hero section, features, and call-to-action.

Login Page

Login Page Clean authentication interface with email/password and Google OAuth options.

Course Directory

Course Directory Browse and search through available courses with filtering and sorting capabilities.


✨ Key Features

  • Authentication: Email/password + Google OAuth via Auth.js v5 with JWT sessions
  • Course Directory: Searchable, filterable grid of published courses
  • Lesson Viewer: Protected lesson player with sidebar navigation
  • Free Preview: Individual lessons can be unlocked as free previews without auth
  • Access Control: /courses route is gated β€” only authenticated users can access
  • Learner Dashboard: Profile info, order history, membership status, account settings
  • Responsive Design: Fully mobile-responsive across all pages
  • SEO Ready: Proper <title>, <meta description>, and semantic HTML on every page

πŸ— Architecture

System Flow

TWP Flow Diagram

Mermaid Architecture Diagram

flowchart TD
  Browser["🌐 Browser (User)"]

  Browser -->|"Public route (/)"|Landing["Landing Page\n(Server Component)"]
  Browser -->|"Auth route (/login, /register)"|Auth["Auth Pages\n(Client Component)"]
  Browser -->|"Protected route (/courses, /profile…)"|Guard["Auth Guard\n(auth() check)"]

  Auth -->|"signIn() / register()"|AuthJS["Auth.js v5\n(JWT Strategy)"]
  AuthJS --> DB["Prisma 7\n+ Neon Postgres"]

  Guard -->|"session valid"|AppPages["App Pages\n(Server Components)"]
  Guard -->|"no session"|Auth

  AppPages -->|"Server Actions\n(src/actions/*)"|DB

  DB --> Models["User Β· Course Β· Lesson\nEnrollment Β· Progress\nPlan Β· Subscription"]

  style Browser fill:#f3f4f6,stroke:#6b7280
  style AuthJS fill:#8b5cf6,stroke:#6d28d9,color:#fff
  style DB fill:#f59e0b,stroke:#b45309,color:#fff
  style Guard fill:#ef4444,stroke:#991b1b,color:#fff
  style AppPages fill:#3b82f6,stroke:#0369a1,color:#fff
Loading

Page Structure

Route Type Auth Required
/ Public landing page No
/login Sign in No
/register Sign up No
/courses Course directory βœ… Yes
/courses/[slug] Course curriculum βœ… Yes
/courses/[slug]/lessons/[id] Lesson player βœ… Yes (or preview)
/profile Learner profile βœ… Yes
/orders Order history βœ… Yes
/memberships Membership status βœ… Yes
/settings Account settings βœ… Yes

Data Model

erDiagram
    User ||--o{ Account : "OAuth accounts"
    User ||--o{ Subscription : has
    User ||--o{ Enrollment : enrolled
    User ||--o{ Progress : tracks

    Course ||--o{ Lesson : contains
    Course ||--o{ Enrollment : enrollments

    Lesson ||--o{ Progress : tracked_in

    Plan ||--o{ Subscription : defines

    User {
        string id PK
        string name
        string email UK
        string password
        Role   role
        datetime createdAt
    }

    Course {
        string  id PK
        string  title
        string  slug UK
        string  description
        boolean is_published
    }

    Lesson {
        string  id PK
        string  courseId FK
        string  title
        string  video_url
        boolean is_preview
        int     order
    }

    Enrollment {
        string   id PK
        string   userId FK
        string   courseId FK
        datetime started_at
    }

    Progress {
        string  id PK
        string  userId FK
        string  lessonId FK
        boolean completed
    }

    Plan {
        string id PK
        string name
        int    price_monthly
        int    price_yearly
        string stripe_price_id
    }

    Subscription {
        string   id PK
        string   userId FK
        string   planId FK
        string   status
        datetime current_period_end
        string   stripe_subscription_id
    }
Loading

πŸ› οΈ Tech Stack

Frontend

Layer Tech
Framework Next.js 16 (App Router)
Language TypeScript
Styling Tailwind CSS v4 + Vanilla CSS (CSS Variables)
Fonts Plus Jakarta Sans, Inter (Google Fonts)
Icons react-icons
Validation Zod

Backend & Data

Service Tech
Authentication Auth.js v5 (JWT, Credentials + Google OAuth)
ORM Prisma 7
Database PostgreSQL via Neon (serverless)
Server Logic Next.js Server Actions (src/actions/)
DB Adapter @prisma/adapter-neon

Infrastructure

Aspect Solution
Hosting Vercel
CI/CD Vercel Auto-Deploy
Database Neon Postgres (serverless)
Version Control Git + GitHub

πŸ“ Project Structure

src/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ (auth)/              # Login & Register pages
β”‚   β”‚   β”œβ”€β”€ login/
β”‚   β”‚   └── register/
β”‚   β”œβ”€β”€ (dashboard)/         # Authenticated user pages
β”‚   β”‚   β”œβ”€β”€ layout.tsx       # Shared header + sidebar layout
β”‚   β”‚   β”œβ”€β”€ profile/
β”‚   β”‚   β”œβ”€β”€ orders/
β”‚   β”‚   β”œβ”€β”€ memberships/
β”‚   β”‚   └── settings/
β”‚   β”œβ”€β”€ api/auth/            # Auth.js route handler
β”‚   β”œβ”€β”€ courses/
β”‚   β”‚   β”œβ”€β”€ page.tsx         # Course directory
β”‚   β”‚   └── [slug]/
β”‚   β”‚       β”œβ”€β”€ page.tsx     # Course curriculum
β”‚   β”‚       └── lessons/
β”‚   β”‚           └── [lessonId]/page.tsx  # Lesson player
β”‚   β”œβ”€β”€ page.tsx             # Landing page
β”‚   β”œβ”€β”€ layout.tsx           # Root layout
β”‚   └── globals.css          # Design tokens + Tailwind
β”œβ”€β”€ actions/
β”‚   β”œβ”€β”€ auth.actions.ts      # login(), register()
β”‚   └── course.actions.ts    # getCourseBySlug(), getLessonById()…
β”œβ”€β”€ auth.ts                  # Auth.js (PrismaAdapter + JWT callbacks)
β”œβ”€β”€ auth.config.ts           # Providers: Google + Credentials
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ course/              # CourseCard, CoursesList, LessonSidebar
β”‚   β”œβ”€β”€ dashboard/           # DashboardSidebar
β”‚   β”œβ”€β”€ layout/              # Navbar, Footer, ProfileDropdown
β”‚   β”œβ”€β”€ sections/            # Landing page sections
β”‚   └── ui/                  # Shadcn-based: Button, Input, Login1
β”œβ”€β”€ hooks/
β”‚   └── useScrollReveal.ts
└── lib/
    β”œβ”€β”€ db.ts                # Prisma singleton
    └── utils.ts             # cn() utility
prisma/
β”œβ”€β”€ schema.prisma
└── seed.ts

πŸš€ Getting Started

Prerequisites

  • Node.js 18+
  • A PostgreSQL database (recommend Neon β€” free tier available)
  • Google OAuth credentials (optional, for Google login)

Quick Start

1. Clone the repository

git clone https://github.com/wayphantomme/tech-with-phantom.git
cd tech-with-phantom

2. Install dependencies

npm install

3. Set up environment variables

cp .env.example .env
# Fill in your values (see Environment Variables section below)

4. Push database schema

npx prisma db push

5. Seed sample data (optional)

npx prisma db seed

6. Start development server

npm run dev

Open http://localhost:3000


πŸ” Environment Variables

Create a .env file in the project root:

# Database (Neon Postgres)
DATABASE_URL="postgresql://..."

# Auth.js
AUTH_SECRET="your-secret-here"   # generate: openssl rand -base64 32

# Google OAuth (optional)
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""

πŸ“¦ Database & Prisma

npx prisma db push         # Push schema to database (no migration files)
npx prisma migrate dev     # Create & apply a new migration
npx prisma db seed         # Run seed.ts to insert sample courses
npx prisma studio          # Open visual database browser

The Prisma client is exposed as a singleton via src/lib/db.ts using the @prisma/adapter-neon for serverless-compatible connections.


βš™οΈ Deployment

Recommended: Vercel + Neon

  1. Push this repo to GitHub
  2. Import the project into Vercel
  3. Set all environment variables in Vercel's project settings
  4. Deploy β€” Vercel auto-detects Next.js

Important: DATABASE_URL and AUTH_SECRET are required in production. For Google OAuth, also set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET, and add https://your-domain.com/api/auth/callback/google to your Google Cloud Console redirect URIs.


πŸ“„ License

This project is open-source and available under the MIT License.

About

[Edutech] Modern online course platform built with Next.js and Prisma, designed to easily scale and manage your digital education business.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages