A full-stack, real-time mentor-mentee video meeting platform built with Next.js 14, Convex, Clerk, and Stream Video SDK. Saarthi enables mentors (interviewers) to schedule, manage, and conduct 1-on-1 or group mentoring sessions with mentees (candidates) — complete with live video calls, an in-call notes editor, session ratings, and a comprehensive dashboard.
- Features
- Tech Stack
- Architecture Overview
- Database Schema
- Project Structure
- Getting Started
- Environment Variables
- User Roles & Permissions
- Key Pages & Routes
- How It Works
- Screenshots
- License
| Feature | Description |
|---|---|
| 🔐 Authentication | Clerk-powered sign-in/sign-up with automatic user sync to Convex via webhooks |
| 👥 Role-Based Access | Two distinct roles — Mentor (Interviewer) and Mentee (Candidate) — with tailored dashboards |
| 📅 Session Scheduling | Mentors can schedule sessions by picking a date, time slot, mentee, and co-mentors |
| ⚡ Instant Meetings | Start an ad-hoc video call instantly with a single click |
| 🔗 Join via Link | Mentees or mentors can join any meeting by pasting the invitation link |
| 📹 Live Video Calls | Powered by Stream Video SDK with Speaker and Grid layout options |
| 📝 In-Call Notes Editor | Monaco-based Markdown editor embedded in the meeting room for live note-taking |
| 💬 Comments & Ratings | Mentors can leave post-session comments with a 1–5 star rating |
| ✅ Session Outcomes | Mark completed sessions as Successful or Needs Work |
| 📊 Mentor Dashboard | Grouped view of all sessions — Upcoming, Completed, Succeeded, and Failed |
| 🌗 Dark / Light Mode | System-aware theme toggle using next-themes |
| 🎨 Animated Landing Page | Beautiful landing page with Framer Motion animations |
| 🔔 Toast Notifications | Real-time feedback for all user actions via react-hot-toast |
| 📄 Export Support | PDF and DOCX export capabilities via jsPDF and docx |
- Next.js 14 — App Router, Server Actions, File-based routing
- React 18 — Component-based UI
- TypeScript — End-to-end type safety
- Tailwind CSS — Utility-first styling
- shadcn/ui + Radix UI — Accessible, composable UI primitives
- Framer Motion — Animations & transitions
- Monaco Editor — VS Code-grade in-browser editor
- Lucide React — Icon library
- Convex — Real-time serverless backend with reactive queries and mutations
- Clerk — Authentication, user management, and webhook-based user sync
- Svix — Webhook signature verification for Clerk events
- Stream Video React SDK — Video calling UI components (call controls, participant lists, layouts)
- Stream Node SDK — Server-side token generation for secure video sessions
- date-fns — Date formatting and manipulation
- jsPDF — Client-side PDF generation
- docx — DOCX document generation
- react-hot-toast — Lightweight toast notifications
┌─────────────────────────────────────────────────────────┐
│ Client (Browser) │
│ ┌──────────┐ ┌──────────┐ ┌────────────────────────┐ │
│ │ Clerk │ │ Convex │ │ Stream Video React │ │
│ │ Auth UI │ │ React │ │ SDK (Video Calls) │ │
│ └────┬─────┘ └────┬─────┘ └──────────┬─────────────┘ │
└───────┼──────────────┼──────────────────┼───────────────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ Clerk API │ │ Convex Cloud │ │ Stream Video │
│ (Auth + JWT) │ │ (Database │ │ (WebRTC Calls) │
│ │ │ + Functions)│ │ │
└──────┬───────┘ └──────────────┘ └──────────────────┘
│ ▲
│ Webhook (user.created) │
▼ │
┌──────────────┐ ┌─────────────┴──────┐
│ Convex HTTP │ │ Next.js Server │
│ Endpoint │ │ Action (Token │
│ /clerk-webhook│ │ Generation) │
└──────────────┘ └────────────────────┘
- Clerk handles authentication and emits a
user.createdwebhook on sign-up. - The Convex HTTP endpoint (
/clerk-webhook) receives the webhook, verifies the Svix signature, and inserts the user into the Convexuserstable with a defaultcandidaterole. - Convex serves as the real-time database — all queries are reactive and auto-update the UI when data changes.
- Stream Video SDK provides the video calling infrastructure. Tokens are generated server-side via a Next.js Server Action using the Stream Node SDK.
The Convex database consists of three tables:
| Field | Type | Description |
|---|---|---|
name |
string |
Full name of the user |
email |
string |
Email address |
image |
string? |
Profile avatar URL (optional) |
role |
"candidate" | "interviewer" |
User role — mentee or mentor |
clerkId |
string |
Clerk user ID (indexed) |
| Field | Type | Description |
|---|---|---|
title |
string |
Session title |
description |
string? |
Optional session description |
startTime |
number |
Scheduled start time (epoch ms) |
endTime |
number? |
Actual end time (set when completed) |
status |
string |
"upcoming" · "completed" · "succeeded" · "failed" |
streamCallId |
string |
Stream Video call ID (indexed) |
candidateId |
string |
Clerk ID of the mentee |
interviewerIds |
string[] |
Clerk IDs of assigned mentors |
| Field | Type | Description |
|---|---|---|
content |
string |
Comment text |
rating |
number |
Star rating (1–5) |
interviewerId |
string |
Clerk ID of the commenting mentor |
interviewId |
Id<"interviews"> |
Reference to the parent session |
Mentor-Meet-Booking/
├── convex/ # Convex backend
│ ├── schema.ts # Database schema definitions
│ ├── users.ts # User queries & mutations (sync, getUsers, getByClerkId)
│ ├── interviews.ts # Interview/session CRUD operations
│ ├── comments.ts # Comment & rating mutations/queries
│ ├── http.ts # HTTP router for Clerk webhook endpoint
│ ├── auth.config.ts # Convex ↔ Clerk auth provider config
│ └── _generated/ # Auto-generated Convex types & API
│
├── src/
│ ├── middleware.ts # Clerk authentication middleware
│ │
│ ├── actions/
│ │ └── stream.actions.ts # Server Action — Stream video token generation
│ │
│ ├── app/
│ │ ├── page.tsx # Landing page (public, animated with Framer Motion)
│ │ ├── layout.tsx # Root layout (Clerk provider)
│ │ └── app/ # Authenticated app routes
│ │ ├── layout.tsx # App layout (Convex + Clerk + Theme + Navbar)
│ │ ├── (root)/
│ │ │ ├── layout.tsx # Wraps children with StreamClientProvider
│ │ │ ├── (home)/
│ │ │ │ └── page.tsx # Home — quick actions (mentor) or meeting list (mentee)
│ │ │ ├── schedule/
│ │ │ │ ├── page.tsx # Guard — only mentors can access
│ │ │ │ └── InterviewScheduleUI.tsx # Full scheduling form + session list
│ │ │ └── meeting/
│ │ │ └── [id]/
│ │ │ └── page.tsx # Video meeting room (setup → call)
│ │ ├── (admin)/
│ │ │ └── dashboard/
│ │ │ └── page.tsx # Mentor dashboard — grouped sessions + outcomes
│ │ └── api/ # API routes (DOCX export, code execution, Gemini)
│ │
│ ├── components/
│ │ ├── Navbar.tsx # Top navigation bar with role-aware buttons
│ │ ├── MeetingRoom.tsx # Video call room with resizable code editor panel
│ │ ├── MeetingSetup.tsx # Pre-call device setup screen
│ │ ├── MeetingModal.tsx # Start / Join meeting dialog
│ │ ├── MeetingCard.tsx # Session card with live/upcoming/completed status
│ │ ├── ActionCard.tsx # Quick action card (New Call, Join, Schedule)
│ │ ├── CodeEditor.tsx # Monaco-based in-call Markdown notes editor
│ │ ├── CommentDialog.tsx # Post-session comment + rating dialog
│ │ ├── EndCallButton.tsx # End call for all participants (owner only)
│ │ ├── DasboardBtn.tsx # Dashboard nav button (mentors only)
│ │ ├── ModeToggle.tsx # Dark/Light theme toggle
│ │ ├── LoaderUI.tsx # Full-screen loading spinner
│ │ ├── providers/
│ │ │ ├── ConvexClerkProvider.tsx # Convex + Clerk auth integration
│ │ │ ├── StreamClientProvider.tsx # Stream Video client initialization
│ │ │ └── ThemeProvider.tsx # next-themes provider
│ │ └── ui/ # shadcn/ui component library
│ │
│ ├── hooks/
│ │ ├── useUserRole.ts # Returns { isInterviewer, isCandidate, isLoading }
│ │ ├── useGetCallById.ts # Fetches a Stream call by ID
│ │ ├── useGetCalls.ts # Fetches user's calls from Stream
│ │ └── useMeetingActions.ts # createInstantMeeting() & joinMeeting() helpers
│ │
│ ├── constants/
│ │ └── index.ts # Quick actions, time slots, interview categories, coding questions
│ │
│ └── lib/
│ └── utils.ts # Helpers — groupInterviews, getCandidateInfo, getMeetingStatus
│
├── public/ # Static assets
├── package.json
├── tailwind.config.ts
├── tsconfig.json
├── next.config.mjs
└── postcss.config.mjs
- Node.js ≥ 18
- npm or yarn or pnpm
- A Clerk account
- A Convex account
- A Stream account (Video & Audio API)
# 1. Clone the repository
git clone https://github.com/your-username/Mentor-Meet-Booking.git
cd Mentor-Meet-Booking
# 2. Install dependencies
npm install
# 3. Set up environment variables (see section below)
cp .env.example .env.local
# 4. Start the Convex dev server (in a separate terminal)
npx convex dev
# 5. Start the Next.js dev server
npm run devThe app will be running at http://localhost:3000.
Create a .env.local file in the project root with the following variables:
# Clerk Authentication
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
CLERK_WEBHOOK_SECRET=whsec_...
# Convex
NEXT_PUBLIC_CONVEX_URL=https://your-project.convex.cloud
# Stream Video
NEXT_PUBLIC_STREAM_API_KEY=your_stream_api_key
STREAM_SECRET_KEY=your_stream_secret_key- Clerk Webhook: In the Clerk Dashboard, create a webhook endpoint pointing to your Convex HTTP endpoint (
https://<your-convex-deployment>.convex.site/clerk-webhook) and subscribe to theuser.createdevent. - Convex Auth: The Convex auth config is already set up in
convex/auth.config.ts— update thedomainfield with your Clerk issuer URL. - Stream: Create a Stream app with Video & Audio enabled and copy the API key and secret.
| Capability | Mentor (Interviewer) | Mentee (Candidate) |
|---|---|---|
| View Home Dashboard | ✅ (Quick Actions) | ✅ (Meeting List) |
| Start Instant Meeting | ✅ | ❌ |
| Join Meeting via Link | ✅ | ✅ |
| Schedule Sessions | ✅ | ❌ |
| Access Mentor Dashboard | ✅ | ❌ |
| End Meeting for All | ✅ (Owner only) | ❌ |
| Leave Comments & Ratings | ✅ | ❌ |
| Mark Session Outcome | ✅ | ❌ |
| Use In-Call Notes Editor | ✅ | ✅ |
New users are assigned the candidate (mentee) role by default. Roles can be updated directly in the Convex database.
| Route | Access | Description |
|---|---|---|
/ |
Public | Animated landing page with sign-in CTA |
/app |
Auth | Home — Quick actions (mentors) or meeting list (mentees) |
/app/schedule |
Mentors only | Schedule new mentoring sessions |
/app/meeting/[id] |
Auth | Live video meeting room with notes editor |
/app/dashboard |
Mentors only | Manage all sessions, mark outcomes, add comments |
When a user signs up via Clerk, a user.created webhook fires. The Convex HTTP endpoint at /clerk-webhook verifies the Svix signature and creates a user record in the users table with the default candidate role.
A mentor navigates to /app/schedule, fills in the session title, description, date, time slot, selects a mentee, and optionally adds co-mentors. This:
- Creates a Stream Video call with the scheduled start time
- Inserts an interview record in Convex with status
"upcoming"
- Mentees see their scheduled sessions on the home page and click "Join Meeting" when the session is live.
- Mentors can start instant meetings or join via invitation link.
- The meeting page (
/app/meeting/[id]) loads a pre-call setup screen for camera/mic configuration, then transitions to the full meeting room.
The meeting room features a resizable split layout:
- Left panel: Live video call with Speaker or Grid layout, call controls, and participant list
- Right panel: Monaco-based Markdown notes editor for real-time note-taking
The meeting owner (creator) has an End Meeting button that ends the call for all participants and updates the session status to "completed".
On the mentor dashboard, completed sessions can be:
- Marked as Successful ✅ or Needs Work ❌
- Annotated with comments and star ratings (1–5) by any mentor
Sessions are grouped into four categories: Upcoming, Completed, Succeeded, and Failed.
Add screenshots of your landing page, home dashboard, scheduling UI, meeting room, and mentor dashboard here.
This project is private. All rights reserved.
Built with ❤️ using Next.js, Convex, Clerk & Stream