Skip to content

Gurveer2711/Learnary

Repository files navigation

Learnary

A modern Learning Management System (LMS) built with Next.js that provides real-time AI-powered voice teaching lessons for personalized learning experiences. Learnary combines voice AI (VAPI), Supabase, and Clerk to deliver interactive tutoring sessions with natural conversation.


Table of Contents


Features

Feature Description
AI Teaching Lessons Interactive AI tutors for subjects: Maths, Language, Science, History, Coding, Economics
Real-time Voice Sessions Engage with your tutor through live voice conversation via VAPI
Personalized Journeys Track lessons completed, lessons created, and session history
Lesson Library Browse, search, and filter lessons by subject and topic
Lesson Builder Create custom lessons with name, subject, topic, duration, style, and voice
Subscription Tiers Plan limits (3 or 10 companions) with Clerk pricing; Pro = unlimited
Bookmarking UI Bookmark button on lesson cards (UI ready)
Error Monitoring Sentry integration for error tracking

Tech Stack

Category Technology
Framework Next.js 15.3 (App Router, Turbopack)
Language TypeScript
Auth Clerk
Database Supabase (PostgreSQL)
Voice AI VAPI (@vapi-ai/web)
Styling Tailwind CSS 4
UI Components Radix UI, HeroUI, shadcn/ui (Button, Form, Input, Select, etc.)
Forms React Hook Form + Zod
Animations Framer Motion, Lottie React
Error Tracking Sentry
Font Bricolage Grotesque

User Flow Flowchart

flowchart TD
    Start([Visitor arrives]) --> Home[/]
    Home --> Auth{Authenticated?}
    Auth -->|No| SignIn[/sign-in]
    Auth -->|Yes| Dashboard[Dashboard /]
    
    SignIn --> Clerk[Clerk Sign In]
    Clerk --> Dashboard
    
    Dashboard --> Nav[Navigation]
    Nav --> HomeLink[Home]
    Nav --> LessonsLink[Lesson Library]
    Nav --> JourneyLink[My Journey]
    
    HomeLink --> Home
    LessonsLink --> Library[/companions]
    JourneyLink --> Journey[/my-journey]
    
    Library --> Search[Search & Filter by subject/topic]
    Search --> Library
    
    Library --> NewLesson[New Lesson]
    NewLesson --> Builder[/companions/new]
    
    Builder --> LimitCheck{Limit reached?}
    LimitCheck -->|Yes| Upgrade[/subscription]
    LimitCheck -->|No| Form[Lesson Builder Form]
    
    Upgrade --> Pricing[Clerk Pricing Table]
    
    Form --> Create[Create Companion]
    Create --> Session[/companions/:id]
    
    Library --> Card[Lesson Card]
    Card --> Launch[Launch Lesson]
    Launch --> Session
    
    Session --> Voice[Voice Session - VAPI]
    Voice --> Controls[Start / End Session, Mute]
    Controls --> Transcript[Live Transcript]
    Controls --> End[End Session]
    
    End --> SaveSession[Save to session_history]
    SaveSession --> Journey
    
    Journey --> Stats[Lessons Completed / Lessons Created]
    Stats --> Accordion[Accordion: Session History & Created]
    Accordion --> Reopen[Reopen Lesson]
    Reopen --> Session
    
    Dashboard --> Recent[Recent Sessions]
    Dashboard --> CTA[Build New Lesson CTA]
    CTA --> Builder
Loading

User Flow Summary

  1. Landing: User visits / (Dashboard or redirect if unauthenticated).
  2. Auth: Signs in via Clerk at /sign-in.
  3. Browse: Uses Home, Lesson Library (/companions), and My Journey (/my-journey).
  4. Search: Filters lessons by subject and topic on the library page.
  5. Create: Goes to Lesson Builder (/companions/new); if limit reached, directed to /subscription.
  6. Learn: Launches a lesson from a card → /companions/[id] → starts VAPI voice session.
  7. Interact: Uses Start/End Session, mute, and sees live transcript.
  8. Track: Completed sessions appear in My Journey.

Project Structure

Learnary/
├── app/
│   ├── layout.tsx              # Root layout (ClerkProvider, font, grid bg)
│   ├── page.tsx                # Dashboard (home)
│   ├── globals.css             # Global styles
│   ├── global-error.tsx        # Global error boundary
│   ├── sign-in/
│   │   └── [[...sign-in]]/
│   │       └── page.tsx        # Clerk sign-in
│   ├── companions/
│   │   ├── page.tsx            # Lesson Library (search, filter, grid)
│   │   ├── new/
│   │   │   └── page.tsx        # Lesson Builder (form or limit upsell)
│   │   └── [id]/
│   │       └── page.tsx        # Lesson session (VAPI voice)
│   ├── my-journey/
│   │   └── page.tsx            # Profile: sessions & created lessons
│   ├── subscription/
│   │   └── page.tsx            # Clerk PricingTable
│   ├── api/
│   │   └── sentry-example-api/
│   │       └── route.ts        # Sentry test API
│   └── sentry-example-page/
│       └── page.tsx            # Sentry test page
├── components/
│   ├── Navbar.tsx              # Main nav + Sign In / UserButton
│   ├── NavItems.tsx            # Home, Lessons, My Journey links
│   ├── LessonCard.tsx          # Lesson card with Launch + bookmark
│   ├── LessonList.tsx          # Table of lessons (recent/created/completed)
│   ├── LessonForm.tsx          # Lesson builder form
│   ├── LessonComponent.tsx     # VAPI voice session UI + transcript
│   ├── SearchInput.tsx         # Topic search (debounced)
│   ├── SubjectFilter.tsx       # Subject dropdown filter
│   ├── Cta.tsx                 # CTA "Build New Lesson"
│   ├── Footer.tsx
│   └── ui/
│       ├── accordion.tsx
│       ├── button.tsx
│       ├── command.tsx
│       ├── dialog.tsx
│       ├── form.tsx
│       ├── input.tsx
│       ├── label.tsx
│       ├── popover.tsx
│       ├── select.tsx
│       ├── table.tsx
│       └── textarea.tsx
├── lib/
│   ├── actions/
│   │   └── companion.actions.ts # Server actions for companions & sessions
│   ├── supabase.ts             # Supabase client (uses Clerk token)
│   ├── vapi.sdk.ts             # VAPI client
│   └── utils.ts                # cn, getSubjectColor, configureAssistant
├── constants/
│   ├── index.ts                # subjects, subjectsColors, voices, recentSessions
│   └── soundwaves.json         # Lottie animation for voice
├── types/
│   ├── index.d.ts              # Companion, CreateCompanion, etc.
│   └── vapi.d.ts               # VAPI type augmentations
├── public/
│   ├── icons/                  # SVG icons (bookmark, cap, clock, subjects, etc.)
│   └── images/                 # cta.svg, limit.svg
├── middleware.ts               # Clerk auth middleware
├── next.config.ts              # Sentry, image domains (img.clerk.com)
├── tailwind.config.js
├── tsconfig.json
├── postcss.config.mjs
├── instrumentation.ts          # Sentry server
├── instrumentation-client.ts   # Sentry client
├── sentry.edge.config.ts
├── sentry.server.config.ts
├── components.json             # shadcn config
└── package.json

Getting Started

Prerequisites

  • Node.js 20+
  • npm or pnpm
  • Supabase project
  • Clerk application
  • VAPI account and web token

Installation

# Clone the repository
git clone <repo-url>
cd Learnary

# Install dependencies
npm install

# Copy environment variables
cp .env.example .env.local
# Edit .env.local with your keys

Run Locally

npm run dev

Open http://localhost:3000.


Environment Variables

Create .env.local with:

Variable Description Required
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY Clerk publishable key Yes
CLERK_SECRET_KEY Clerk secret key Yes
NEXT_PUBLIC_SUPABASE_URL Supabase project URL Yes
NEXT_PUBLIC_SUPABASE_ANON_KEY Supabase anon/public key Yes
NEXT_PUBLIC_VAPI_WEB_TOKEN VAPI web SDK public token Yes
NEXT_PUBLIC_SENTRY_DSN Sentry DSN (optional) No

Data Model

Tables

companions

Column Type Description
id uuid Primary key
author string Clerk user ID
name string Lesson name
subject string maths, language, science, history, coding, economics
topic string Lesson topic/description
duration number Duration in minutes
style string casual / formal
voice string male / female
created_at timestamp Creation time

session_history

Column Type Description
id uuid Primary key
companion_id uuid FK → companions
user_id string Clerk user ID
created_at timestamp Session completion time

Routes & Pages

Route Description Auth
/ Dashboard: featured lessons + recent sessions + CTA Optional
/companions Lesson library with search and subject filter Optional
/companions/new Lesson builder or limit upsell Required
/companions/[id] Voice session page Required
/my-journey Profile, stats, lessons completed/created Required
/sign-in Clerk sign-in No
/subscription Clerk PricingTable Optional

Components

Component Role
Navbar Logo, NavItems, Sign In / UserButton
NavItems Home, Lessons, My Journey (active state)
LessonCard Card with subject badge, topic, duration, Launch Lesson, bookmark
LessonList Table of lessons (name, topic, subject, duration)
LessonForm Zod-validated form: name, subject, topic, duration, style, voice
LessonComponent VAPI session: Start/End, mute, Lottie animation, transcript
SearchInput Debounced topic search (URL params)
SubjectFilter Subject dropdown (URL params)
Cta “Build New Lesson” CTA with link to builder

Server Actions

All in lib/actions/companion.actions.ts:

Action Purpose
createCompanion(formData) Insert new companion (author from Clerk)
getAllCompanions({ limit, page, subject, topic }) List companions with filters
getCompanion(id) Get single companion by id
addToSessionHistory(companionId) Insert session record on call end
getRecentSession(limit) Recent sessions (for dashboard)
getUserSession(userId, limit) Sessions for a user
getUserCompanions(userId) Companions created by user
newCompanionPermissions() Check plan limit (Pro = unlimited, else 3 or 10)

Third-Party Integrations

Service Usage
Clerk Auth, UserButton, SignIn, pricing (plans)
Supabase companions and session_history storage
VAPI Voice AI: 11labs voices, Deepgram transcriber, GPT-4
Sentry Error monitoring and source maps
Lottie Soundwave animation during voice session

Configuration

  • Clerk: Primary color #1E3A8A
  • Images: Remote patterns include img.clerk.com
  • Sentry: Org gurveer-20, project javascript-nextjs
  • Voice: Male/female + casual/formal (see constants/index.ts)

Scripts

Script Command Description
dev next dev --turbopack Development server
build next build Production build
start next start Start production server
lint next lint Run ESLint

Notes

  • Lesson routes use /companions internally; renaming to /lessons would require redirects and import updates.
  • Bookmark UI is present on LessonCard; backend persistence is not implemented.
  • Supabase client uses Clerk JWT via auth().getToken() for RLS-friendly access.

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors