EduConnect is a comprehensive, full-stack education consultation platform that enables seamless appointment scheduling between students and verified education professionals. The platform provides real-time video consultation capabilities, credit-based booking system, and robust admin management tools.
- teacher-student Matching: Browse and filter teachers by specialty
- Appointment Scheduling: Real-time slot management and booking system
- Video Consultation: Integrated video calls using Vonage Video API
- Credit System: Token-based appointment purchasing with tiered plans
- teacher Verification: Multi-level authentication and credentialing system
- Payout Management: Automated payment processing for healthcare providers
- Admin Dashboard: Comprehensive management and monitoring tools
- Dark Mode Support: Theme switching with next-themes
- Technology Stack
- Project Architecture
- Installation & Setup
- Environment Configuration
- Suggested Workflows
- API Documentation
- Database Schema
- Development Guidelines
- Deployment
| Technology | Version | Purpose |
|---|---|---|
| Next.js | 15.3.2 | Full-stack React framework with App Router |
| React | 19.1.0 | UI library |
| TailwindCSS | 4.1.7 | Utility-first CSS framework |
| Shadcn/ui | Latest | Pre-built accessible components |
| React Hook Form | 7.56.3 | Performant form validation |
| Zod | 3.24.4 | TypeScript-first schema validation |
| Lucide React | 0.510.0 | Icon library |
| Sonner | 2.0.3 | Toast notifications |
| React Spinners | 0.17.0 | Loading indicators |
| next-themes | 0.4.6 | Theme management |
| Technology | Version | Purpose |
|---|---|---|
| Prisma | 6.9.0 | ORM for database management |
| PostgreSQL | - | Relational database |
| Technology | Version | Purpose |
|---|---|---|
| @clerk/nextjs | 6.19.3 | User authentication & management |
| @clerk/themes | 2.2.43 | Clerk UI theming |
| Technology | Version | Purpose |
|---|---|---|
| @vonage/server-sdk | 3.21.0 | Video session management |
| @vonage/client-sdk-video | 2.30.0 | Video client library |
| @vonage/video | 1.23.0 | Video integration |
| @vonage/auth | 1.12.0 | Vonage authentication |
| opentok | 2.21.2 | OpenTok video API |
| Component | Library |
|---|---|
| Alerts & Dialogs | @radix-ui |
| Forms & Inputs | @radix-ui + Shadcn |
| Tabs & Navigation | @radix-ui |
| Dropdowns | Radix UI Select |
| Tool | Version | Purpose |
|---|---|---|
| ESLint | 9 | Code linting |
| PostCSS | 8.5.3 | CSS transformation |
| Autoprefixer | 10.4.21 | CSS vendor prefixes |
EduConnect/
├── app/ # Next.js App Router
│ ├── (auth)/ # Authentication routes (public)
│ │ ├── sign-in/
│ │ └── sign-up/
│ ├── (main)/ # Main application (protected)
│ │ ├── admin/ # Admin dashboard
│ │ ├── appointments/ # Appointment listing
│ │ ├── teacher/ # teacher dashboard
│ │ ├── teachers/ # teacher discovery & search
│ │ ├── onboarding/ # User role selection
│ │ └── video-call/ # Video consultation UI
│ └── globals.css # Global styles
├── actions/ # Server-side actions (API layer)
│ ├── admin.js # Admin operations
│ ├── appointments.js # Appointment management
│ ├── credits.js # Credit system
│ ├── teacher.js # teacher operations
│ ├── teachers-listing.js # teacher search/filter
│ ├── onboarding.js # User onboarding
│ ├── student.js # student operations
│ ├── payout.js # Payout management
│ └── teachers-listing.js # teacher queries
├── components/ # Reusable React components
│ ├── ui/ # Shadcn/ui components
│ ├── Header.jsx
│ ├── theme-provider.jsx
│ └── appointment-card.jsx
├── hooks/ # Custom React hooks
│ └── use-fetch.js # Data fetching utility
├── lib/ # Utility functions
│ ├── prisma.js # Prisma client instance
│ ├── schema.js # Data validation schemas
│ ├── utils.js # Helper functions
│ ├── checkUser.js # User verification
│ ├── data.js # Data processing
│ └── specialities.js # Medical specialties
├── prisma/ # Database configuration
│ ├── schema.prisma # Data models
│ └── migrations/ # Database migrations
├── public/ # Static assets
├── middleware.js # Clerk authentication middleware
└── package.json # Dependencies
- Node.js 18+ (v19 recommended)
- npm or yarn package manager
- PostgreSQL database
- Clerk account (authentication)
- Vonage account (video API)
# Clone the repository
git clone https://github.com/sparshsharma81/medime1.git
cd EduConnect
# Install dependencies
npm install
# or with legacy peer deps if issues occur
npm install --legacy-peer-depsCreate a .env.local file in the root directory:
# Database
DATABASE_URL="postgresql://user:password@localhost:5432/educonnect"
# Clerk Authentication
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key
CLERK_SECRET_KEY=your_clerk_secret_key
# Vonage Video API
NEXT_PUBLIC_VONAGE_APPLICATION_ID=your_vonage_app_id
VONAGE_PRIVATE_KEY=your_vonage_private_key# Generate Prisma client
npx prisma generate
# Run migrations
npx prisma migrate deploy
# (Optional) Seed test data
npx prisma db seednpm run dev
# or
yarn dev
# or
pnpm devOpen http://localhost:3000 in your browser.
npm run build
npm startEduConnect includes 4 GitHub Actions workflows for CI/CD, testing, and deployment. These workflows run automatically on every push and PR to maintain code quality.
Purpose: Lint code, build application, and run security audits
| Task | Trigger | Details |
|---|---|---|
| ESLint | Every push/PR | Checks code quality with ESLint |
| Build | Every push/PR | Builds Next.js application |
| Type Check | Every push/PR | Validates TypeScript types |
| Security Audit | Every push/PR | Runs npm audit for vulnerable packages |
When to care: If build/lint fails, fix issues before merging
Example Status:
✅ ci/lint - Code quality passed
✅ ci/build - Build successful
✅ ci/type-check - No type errors
✅ ci/security-audit - No critical vulnerabilities
Purpose: Validate database schema and test migrations
| Task | Trigger | Details |
|---|---|---|
| Schema Validation | On schema.prisma changes | Validates Prisma schema syntax |
| Generate Client | On schema.prisma changes | Regenerates Prisma Client |
| Migration Test | On schema.prisma changes | Tests migrations on test database |
When to care: If schema changes fail validation, fix prisma/schema.prisma
Example Status:
✅ prisma/validate-schema - Schema valid
✅ prisma/test-migrations - Migrations successful
Purpose: Auto-deploy to Vercel when main branch is updated
| Task | Trigger | Details |
|---|---|---|
| Build | Push to main | Builds application for production |
| Deploy | Push to main | Deploys to Vercel automatically |
| Slack Notify | Push to main | Sends deployment status to Slack |
When to care: After merging to main, your app auto-deploys. Check Vercel dashboard
Example Status:
✅ Build successful
✅ Deployed to https://sparsh2.vercel.app
✅ Slack notification sent
Purpose: Check for vulnerabilities, outdated packages, and code quality
| Task | Trigger | Details |
|---|---|---|
| Dependency Check | Weekly + on package.json changes | Audits npm packages |
| Snyk Scan | Weekly + on package.json changes | Advanced security scanning |
| CodeQL Analysis | Weekly + on package.json changes | GitHub's code analysis |
| License Check | Weekly + on package.json changes | Checks package licenses |
When to care: If vulnerabilities found, update packages or suppress in review
Example Status:
✅ dependency-check - No moderate vulnerabilities
✅ security-scan - Security passed
✅ codeql - No issues found
✅ license-check - All licenses compatible
Add these to your GitHub repository settings (Settings → Secrets and variables → Actions):
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY → Your Clerk public key
CLERK_SECRET_KEY → Your Clerk secret
DATABASE_URL → Your PostgreSQL connection string
NEXT_PUBLIC_VONAGE_APPLICATION_ID → Your Vonage app ID
VONAGE_PRIVATE_KEY → Your Vonage private key
VERCEL_TOKEN → Your Vercel authentication token
VERCEL_PROJECT_ID → Your Vercel project ID
VERCEL_ORG_ID → Your Vercel org ID
SNYK_TOKEN → (Optional) Snyk security token
SLACK_WEBHOOK → (Optional) Slack webhook for notifications
How to get these:
- Clerk: https://clerk.com/docs/deployments/environments
- Vonage: https://vonage.com/communications-apis/
- Vercel: https://vercel.com/account/tokens
- Snyk: https://app.snyk.io/account/
✅ DO:
- Merge only after all workflows pass
- Keep secrets secure (never commit to repo)
- Review CodeQL findings before deployment
- Monitor Slack notifications for deployment issues
❌ DON'T:
- Force push to main (triggers redeploy)
- Skip workflow failures
- Commit sensitive keys
- Use weak npm passwords
- Create a project at clerk.com
- Configure OAuth providers (Google, GitHub, etc.)
- Get your API keys from Clerk Dashboard
- Configure redirect URIs
- Create a Vonage account at vonage.com
- Create a Video API application
- Generate private key
- Add credentials to
.env.local
# Create database
createdb educonnect
# Verify connection
psql -U postgres -d educonnect -c "SELECT version();"- Function:
setUserRole(formData) - File: actions/onboarding.js
- Auth Required: ✅ Yes (Clerk)
- Parameters:
{ role: "student" | "teacher", specialty?: string, // Required for teacher experience?: number, // Required for teacher credentialUrl?: string, // Required for teacher description?: string // Required for teacher }
- Returns:
{ success: true, redirect: "/teachers" | "/teacher/verification" }
- Description: Initialize user account after sign-up, assign role and collect role-specific information
- Function:
getCurrentUser() - File: actions/onboarding.js
- Auth Required: ✅ Yes (Clerk)
- Parameters: None
- Returns:
{ id: string, clerkUserId: string, email: string, name: string, role: "student" | "teacher" | "ADMIN", credits: number, specialty?: string, experience?: number, verificationStatus?: "PENDING" | "VERIFIED" | "REJECTED" }
- Description: Retrieve authenticated user's complete profile information
- Function:
setAvailabilitySlots(formData) - File: actions/teacher.js
- Auth Required: ✅ Yes (teacher role)
- Parameters:
{ startTime: string, // ISO DateTime endTime: string // ISO DateTime }
- Returns:
{ success: true, message: "Availability set successfully" }
- Validation:
- Start time must be before end time
- teacher must be verified
- Description: Define working hours and available consultation slots
- Function:
getteacherAvailability() - File: actions/teacher.js
- Auth Required: ✅ Yes (teacher role)
- Parameters: None
- Returns:
{ availabilities: [ { id: string, teacherId: string, startTime: DateTime, endTime: DateTime, status: "AVAILABLE" | "BOOKED" | "BLOCKED" } ] }
- Description: Retrieve all availability slots for the authenticated teacher
- Function:
getteacherAppointments() - File: actions/teacher.js
- Auth Required: ✅ Yes (teacher role)
- Parameters: None
- Returns:
{ appointments: [ { id: string, studentId: string, startTime: DateTime, endTime: DateTime, status: "SCHEDULED" | "COMPLETED" | "CANCELLED", student: { name, email, imageUrl }, notes: string } ] }
- Description: Fetch all appointments assigned to the teacher
- Function:
cancelAppointment(formData) - File: actions/teacher.js
- Auth Required: ✅ Yes (teacher role)
- Parameters:
{ appointmentId: string }
- Returns:
{ success: true, message: "Appointment cancelled" }
- Side Effects: Refunds credits to student account
- Description: Cancel scheduled appointment and release booking slot
- Function:
addAppointmentNotes(formData) - File: actions/teacher.js
- Auth Required: ✅ Yes (teacher role)
- Parameters:
{ appointmentId: string, notes: string }
- Returns:
{ success: true }
- Description: Append clinical notes to appointment record
- Function:
markAppointmentCompleted(formData) - File: actions/teacher.js
- Auth Required: ✅ Yes (teacher role)
- Parameters:
{ appointmentId: string }
- Returns:
{ success: true }
- Side Effects: Triggers payout calculation for teacher
- Description: Mark consultation as completed and initiate teacher payment
- Function:
getstudentAppointments() - File: actions/student.js
- Auth Required: ✅ Yes (student role)
- Parameters: None
- Returns:
{ appointments: [ { id: string, teacherId: string, startTime: DateTime, endTime: DateTime, status: "SCHEDULED" | "COMPLETED" | "CANCELLED", teacher: { id, name, specialty, imageUrl }, notes: string } ] }
- Description: Retrieve all booked appointments for the authenticated student
- Function:
bookAppointment(formData) - File: actions/appointments.js
- Auth Required: ✅ Yes (student role)
- Parameters:
{ teacherId: string, startTime: string, // ISO DateTime endTime: string, // ISO DateTime description?: string // student's chief complaint }
- Returns:
{ success: true, appointmentId: string }
- Validation:
- Slot must be within teacher's availability
- student must have sufficient credits (2 credits per appointment)
- Appointment must be in future
- Side Effects:
- Deducts 2 credits from student account
- Creates CreditTransaction record
- Marks availability slot as BOOKED
- Description: Schedule new consultation appointment
- Function:
getteacherById(teacherId) - File: actions/appointments.js
- Auth Required: ❌ No
- Parameters:
{ teacherId: string } - Returns:
{ id: string, name: string, specialty: string, experience: number, description: string, imageUrl: string, verificationStatus: "VERIFIED" | "PENDING" }
- Description: Fetch detailed teacher profile information
- Function:
getAvailableTimeSlots(teacherId) - File: actions/appointments.js
- Auth Required: ❌ No
- Parameters:
{ teacherId: string } - Returns:
{ slots: [ { startTime: DateTime, endTime: DateTime, duration: number // in minutes } ] }
- Description: Get all open booking slots for a teacher
- Function:
generateVideoToken(formData) - File: actions/appointments.js
- Auth Required: ✅ Yes
- Parameters:
{ appointmentId: string }
- Returns:
{ sessionId: string, token: string, apiKey: string }
- Integration: Vonage Video API
- Description: Generate real-time video conference credentials for appointment
- Function:
verifyAdmin() - File: actions/admin.js
- Auth Required: ✅ Yes (Admin role)
- Parameters: None
- Returns:
{ isAdmin: boolean }
- Description: Check if authenticated user has admin privileges
- Function:
getPendingteachers() - File: actions/admin.js
- Auth Required: ✅ Yes (Admin role)
- Parameters: None
- Returns:
{ teachers: [ { id: string, name: string, email: string, specialty: string, experience: number, credentialUrl: string, description: string, verificationStatus: "PENDING" } ] }
- Description: List all teachers awaiting verification
- Function:
getVerifiedteachers() - File: actions/admin.js
- Auth Required: ✅ Yes (Admin role)
- Parameters: None
- Returns:
{ teachers: [ { id: string, name: string, specialty: string, verificationStatus: "VERIFIED", isActive: boolean } ] }
- Description: Retrieve all verified and active teachers
- Function:
updateteacherStatus(formData) - File: actions/admin.js
- Auth Required: ✅ Yes (Admin role)
- Parameters:
{ teacherId: string, status: "VERIFIED" | "REJECTED" }
- Returns:
{ success: true }
- Description: Approve or reject teacher application after credential review
- Function:
updateteacherActiveStatus(formData) - File: actions/admin.js
- Auth Required: ✅ Yes (Admin role)
- Parameters:
{ teacherId: string, isActive: boolean }
- Returns:
{ success: true }
- Description: Activate or deactivate teacher account
- Function:
getPendingPayouts() - File: actions/admin.js
- Auth Required: ✅ Yes (Admin role)
- Parameters: None
- Returns:
{ payouts: [ { id: string, teacherId: string, teacher: { name, email }, amount: number, credits: number, platformFee: number, netAmount: number, paypalEmail: string, status: "PROCESSING" } ] }
- Description: List all pending payout requests from teachers
- Function:
approvePayout(formData) - File: actions/admin.js
- Auth Required: ✅ Yes (Admin role)
- Parameters:
{ payoutId: string }
- Returns:
{ success: true }
- Side Effects: Updates payout status to PROCESSED, records admin approval
- Description: Approve and process teacher payment
- Function:
checkAndAllocateCredits(user) - File: actions/credits.js
- Auth Required: ✅ Yes
- Parameters:
{ user: User object }
- Returns: Updated user object with allocated credits
- Credit Allocation:
- Free Plan: 0 credits/month (starts with 2)
- Standard Plan: 10 credits/month
- Premium Plan: 24 credits/month
- Logic: Checks for existing monthly allocation to prevent duplicate credits
- Description: Auto-allocate monthly credits based on user subscription tier
- Function:
deductCreditsForAppointment(userId, teacherId) - File: actions/credits.js
- Auth Required: ✅ Yes
- Parameters:
{ userId: string, teacherId: string }
- Returns:
{ success: true, remainingCredits: number }
- Cost: 2 credits per appointment
- Validation: student must have minimum 2 credits
- Side Effects: Creates CreditTransaction record
- Description: Deduct consultation cost from student credit balance
- Function:
getteachersBySpecialty(specialty) - File: actions/teachers-listing.js
- Auth Required: ❌ No
- Parameters:
{ specialty: string } - Returns:
{ teachers: [ { id: string, name: string, specialty: string, experience: number, description: string, imageUrl: string, availability: { upcomingSlots: number } } ] }
- Filters: Only returns VERIFIED teachers
- Description: Search and filter teachers by medical specialty
model User {
id String @id @default(uuid())
clerkUserId String @unique // Clerk auth ID
email String @unique
name String?
imageUrl String?
role UserRole @default(UNASSIGNED)
credits Int @default(2) // Appointment credit balance
specialty String? // Medical specialty (teachers only)
experience Int? // Years of experience
credentialUrl String? // Credential verification link
description String? // Bio/About section
verificationStatus VerificationStatus? @default(PENDING)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
teacherAppointments Appointment[] @relation("teacherAppointments")
studentAppointments Appointment[] @relation("studentAppointments")
availabilities Availability[]
transactions CreditTransaction[]
payouts Payout[]
}model Availability {
id String @id @default(uuid())
teacherId String
startTime DateTime
endTime DateTime
status SlotStatus @default(AVAILABLE)
teacher User @relation(fields: [teacherId], references: [id], onDelete: Cascade)
@@index([teacherId, startTime])
}model Appointment {
id String @id @default(uuid())
studentId String
teacherId String
startTime DateTime
endTime DateTime
status AppointmentStatus @default(SCHEDULED)
notes String? // teacher's clinical notes
studentDescription String? // student's chief complaint
videoSessionId String? // Vonage session ID
videoSessionToken String? // Video conference token
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
teacher User @relation("teacherAppointments", fields: [teacherId], references: [id])
student User @relation("studentAppointments", fields: [studentId], references: [id])
@@index([status, startTime])
@@index([teacherId, startTime])
}model CreditTransaction {
id String @id @default(uuid())
userId String
amount Int // Number of credits
type TransactionType // CREDIT_PURCHASE, APPOINTMENT_DEDUCTION, ADMIN_ADJUSTMENT
packageId String? // Subscription plan ID
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}model Payout {
id String @id @default(uuid())
teacherId String
amount Float // Gross amount
credits Int // Number of appointments
platformFee Float // Service fee
netAmount Float // Amount after fees
paypalEmail String // Payment method
status PayoutStatus @default(PROCESSING)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
processedAt DateTime?
processedBy String? // Admin user ID
teacher User @relation(fields: [teacherId], references: [id], onDelete: Cascade)
@@index([status, createdAt])
@@index([teacherId, status])
}enum UserRole {
UNASSIGNED
student
teacher
ADMIN
}
enum VerificationStatus {
PENDING
VERIFIED
REJECTED
}
enum SlotStatus {
AVAILABLE
BOOKED
BLOCKED
}
enum AppointmentStatus {
SCHEDULED
COMPLETED
CANCELLED
}
enum TransactionType {
CREDIT_PURCHASE
APPOINTMENT_DEDUCTION
ADMIN_ADJUSTMENT
}
enum PayoutStatus {
PROCESSING
PROCESSED
}- Server Actions: All database operations use Next.js Server Actions in
/actionsdirectory - Error Handling: Comprehensive try-catch blocks with meaningful error messages
- Validation: Input validation using Zod schemas
- Authentication: All operations validated against Clerk authentication
- Authorization: Role-based access control (student, teacher, ADMIN)
- Create Server Action in appropriate
/actionsfile - Update Database Schema in
prisma/schema.prisma - Generate Migrations:
npx prisma migrate dev - Add UI Components in
/componentsdirectory - Create Routes in
/appfollowing Next.js App Router pattern
# Create migration after schema changes
npx prisma migrate dev --name migration_name
# View migration status
npx prisma migrate status
# Reset database (development only)
npx prisma migrate reset# Run ESLint
npm run lint
# Fix linting issues
npm run lint -- --fix# Install Vercel CLI
npm i -g vercel
# Deploy
vercel
# Set environment variables in Vercel dashboard
# DATABASE_URL, CLERK_SECRET_KEY, VONAGE_PRIVATE_KEY, etc.FROM node:19-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]- Ensure all
.env.localvariables are configured in your deployment platform - Use secure secret management (Vercel Secrets, AWS Secrets Manager, etc.)
- Never commit sensitive keys to version control
{
success: true,
data: { /* endpoint-specific data */ },
message?: "Operation completed successfully"
}{
success: false,
error: "Descriptive error message",
code?: "ERROR_CODE"
}- Fork the repository
- Create feature branch (
git checkout -b feature/AmazingFeature) - Commit changes (
git commit -m 'Add AmazingFeature') - Push to branch (
git push origin feature/AmazingFeature) - Open Pull Request
This project is licensed under the ISC License - see LICENSE file for details.
- Documentation: See inline JSDoc comments in action files
- Issues: Report bugs on GitHub Issues
- Email Support: support@educonnect.com
- Prescription management system
- Medical records storage
- Payment gateway integration (Stripe/Razorpay)
- teacher availability calendar view
- Appointment reminders (SMS/Email)
- Mobile app (React Native)
- Analytics dashboard
- Multi-language support
Last Updated: January 2026
Version: 1.0.0
