A full-stack eLearning platform built with Next.js 15, Express.js, Supabase, and Razorpay.
| Layer | Technology |
|---|---|
| Frontend | Next.js 15 (App Router), TypeScript, Tailwind CSS |
| Backend | Express.js (Node), ES Modules |
| Database | Supabase (PostgreSQL) + Supabase Auth |
| Payments | Razorpay |
| Storage | Supabase Storage (videos, thumbnails, avatars) |
| AI | Groq API (LLaMA models) β summaries, AI chat |
| Auth | Supabase Auth (email magic link, Google, GitHub OAuth) + optional TOTP 2FA |
Skillnora/
βββ frontend/ # Next.js 15 app
β βββ src/app/
β βββ (dashboard)/ # Protected routes (student, instructor, admin)
β β βββ admin/ # Admin overview, courses, payments, studentsβ¦
β β βββ instructor/ # Instructor studio dashboard
β β βββ courses/ # Course detail & lecture player
β β βββ notes/ # Student notes
β β βββ settings/ # User settings & 2FA enrollment
β βββ auth/ # Login / signup page
βββ backend/ # Express API server
β βββ src/features/ # Feature-based modules (courses, enrollments, adminβ¦)
β βββ migrations/ # SQL schema (001_initial_schema.sql)
β βββ server.js
βββ package.json # Root: runs both frontend + backend concurrently
npm install # root (installs concurrently)
cd frontend && npm install
cd ../backend && npm installcp .env.example .envFill in the following in backend/.env:
| Variable | Description |
|---|---|
DATABASE_URL |
Supabase Postgres connection string (pooler) |
SUPABASE_URL |
Your Supabase project URL |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key (server-only) |
SUPABASE_ANON_KEY |
Supabase anon/public key |
RAZORPAY_KEY_ID |
Razorpay Key ID |
RAZORPAY_KEY_SECRET |
Razorpay Key Secret |
GROQ_API_KEY |
Groq API key for AI features |
PORT |
Backend port (default: 5000) |
And in frontend/.env.local:
| Variable | Description |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Supabase anon key |
NEXT_PUBLIC_API_URL |
Backend URL (e.g. http://localhost:5000) |
NEXT_PUBLIC_RAZORPAY_KEY_ID |
Razorpay publishable key |
Open the Supabase SQL editor and run:
backend/migrations/001_initial_schema.sql
This creates all tables, triggers, and RLS policies in one shot.
# From project root β runs both frontend and backend:
npm run dev:all
# Or separately:
npm run dev:api # Express backend on :5000
npm run dev # Next.js frontend on :3000See backend/migrations/001_initial_schema.sql for the full schema.
| Table | Purpose |
|---|---|
users |
User profiles (student / instructor / admin roles) |
courses |
Course catalog with pricing, metadata, and ratings |
lectures |
Individual video lectures within a course |
enrollments |
Tracks which user enrolled in which course |
orders |
Razorpay payment records |
refunds |
Refund ledger (issued when courses are deleted) |
reviews |
Star ratings and review text per course |
certificates |
Issued completion certificates with a unique code |
notes |
Student notes linked to a specific lecture |
lecture_comments |
Q&A discussion threads on lectures |
wishlist_items |
Courses saved to a user's wishlist |
cart_items |
Courses in a user's cart |
notifications |
In-app notification feed |
support_tickets |
User-submitted support requests |
| Status | Meaning |
|---|---|
created |
Order initiated via Razorpay |
paid |
Payment confirmed (Razorpay webhook) |
success |
Alias used in some Razorpay flows |
captured |
Payment captured by Razorpay |
failed |
Payment failed |
refunded |
Payment reversed / refunded |
Revenue Calculation:
SUM(amount WHERE status IN ('paid','success','captured')) - SUM(amount WHERE status = 'refunded')β both admin and instructor dashboards use this identical formula from theorderstable for consistency.
- π Multi-role platform β Student, Instructor, and Admin dashboards
- πΉ Video lectures β Supabase Storage with signed URL generation (6-hour expiry)
- π³ Razorpay payments β Order creation, webhook verification, refund on course deletion
- π Two-Factor Authentication (2FA) β TOTP via Google Authenticator (opt-in per user)
- π Analytics dashboards β Revenue charts, student enrollment trends, course health
- π¬ Q&A discussions β Threaded comments with emoji reactions and image uploads on lectures
- π Notes β Per-lecture notes with direct "Go to Video" deep-link navigation
- π Test Series Engine β Full-featured exam simulator with live timers, anti-cheat mechanisms (tab focus tracking, disable copy/paste), section switching, and a dynamic question palette.
- Mobile-First Design: Test taking experience is highly optimized for mobile devices with swipeable/hideable palettes, proper
100dvhviewport constraints, auto-stacking layouts for options and controls, and zero horizontal clipping. - Auto-Submit: Smart timers that lock the test and seamlessly auto-save/submit answers the exact second the clock expires, redirecting users directly to their analysis.
- Mobile-First Design: Test taking experience is highly optimized for mobile devices with swipeable/hideable palettes, proper
- π Certificates β Auto-issued on course completion with a unique verification code
- π Notifications β Real-time in-app feed for replies, new comments, and support tickets
- π€ AI features β Groq-powered lecture summaries and an AI chat assistant
- π« Support tickets β Users can submit tickets; admin is notified via the notification feed
- Create a Supabase project and copy
SUPABASE_URLandSUPABASE_ANON_KEY. - Add
SUPABASE_SERVICE_ROLE_KEYto your backend env (never expose client-side). - In Authentication β URL Configuration, add your app URL to allowed redirect URLs.
- Enable Google and/or GitHub OAuth providers if needed.
- Run
001_initial_schema.sqlin the SQL editor to create all tables and RLS policies. - Create a Storage bucket named
course-thumbnails(for videos and images).
Both the Admin Dashboard (/admin) and Instructor Dashboard (/instructor) calculate revenue identically:
SUM(amount) FILTER (WHERE status IN ('paid', 'success', 'captured'))
- SUM(amount) FILTER (WHERE status = 'refunded')Student counts only count users with role = 'student' β instructors enrolling in their own free courses for testing are excluded.