An AI-powered course recommendation system disguised as a dating app for University of Otago first-year students
Course Cupid transforms the traditionally overwhelming process of course selection into an engaging, gamified experience. Students can discover their perfect academic matches through personality quizzes, chat with AI-powered "course personalities," and make informed decisions about their first-year papers through a familiar dating app interface.
Course Cupid presents University of Otago first-year papers as individual "personalities" that students can interact with through a dating app paradigm. Each course has its own AI chatbot that embodies the paper's characteristics, making course discovery both informative and entertaining.
- Personality Quiz: AI-powered course matching based on student interests and goals
- Course Chat: Interactive conversations with AI-powered course personalities
- Swipe Interface: Tinder-like UI for course discovery and matching
- Course Database: Comprehensive first-year paper information with real course data
- User Accounts: Session management, match history, and personalized recommendations
- General AI Chat: Cupid chatbot for general academic guidance
- Framework: Vanilla JavaScript with Tailwind CSS
- Structure: Multi-page application with shared components
- Key Pages:
- Landing page with course browsing
- Interactive personality quiz
- Chat interface for course and Cupid conversations
- User authentication and account management
- Server: Node.js with Express.js
- Database: PostgreSQL with custom schema
- AI Integration:
- Google Gemini API for course matching embeddings
- Groq API (Llama) for course personality chat
- Session Management: Express sessions with PostgreSQL storage
- Course Data Ingestion: Web scrapers collect University of Otago course information
- AI Processing: Course descriptions vectorized using Google Gemini embeddings
- User Interaction: Quiz responses processed through similarity matching
- Chat Generation: Course personalities generated via Groq API with contextual prompts
- Match Persistence: User selections stored in PostgreSQL for future reference
- Node.js (v16 or higher)
- Python (3.8 or higher)
- PostgreSQL database
- API keys for Google Gemini and Groq
-
Clone the repository
git clone https://isgb.otago.ac.nz/cosc345/git/grema301/Group_13.git cd Group_13-1 -
Install Node.js dependencies
npm install
-
Set up Python environment
python -m venv venv # Windows venv\Scripts\activate # macOS/Linux source venv/bin/activate pip install -r requirements.txt
-
Environment Configuration Create a
.envfile in the root directory:# Database Configuration DATABASE_URL=postgresql://username:password@localhost:5432/database_name # AI API Keys GEMINI_API_KEY=your_google_gemini_api_key GROQ_API_KEY=your_groq_api_key
-
Database Setup
# Create database schema psql -d your_database -f db/sql-tables.sql # Import course data (optional) node db/importPapers.js
-
Start the application
npm start
-
Access the application
- Navigate to
http://localhost:3000 - Create an account or use as a guest
- Take the personality quiz to get course recommendations
- Navigate to
For production deployment or team collaboration, you can migrate from local PostgreSQL to Supabase cloud database.
# Create and switch to new branch for cloud database
git checkout -b supabaseWe've already set up a shared Supabase database for the Course Cupid project. You don't need to create your own Supabase account or project.
Database Details:
- Shared Database URL: Available from project team
- Pre-configured Schema: Database schema and tables already created
- Course Data: University of Otago course data already imported
Create or update your .env file with the shared Supabase credentials:
# Shared Supabase Database Configuration (get actual URL from team)
# Note: Use transaction pooler URL for free tier (required for IPv4 connections)
DATABASE_URL=postgresql://postgres.coursecupid:[PASSWORD]@aws-0-us-west-1.pooler.supabase.com:6543/postgres
# Direct connection format (only available with paid plans)
# DATABASE_URL=postgresql://postgres:[PASSWORD]@db.coursecupid.supabase.co:5432/postgres
# Session Security
SESSION_SECRET=your_secure_session_secret
# AI API Keys
GEMINI_API_KEY=your_google_gemini_api_key
GROQ_API_KEY=your_groq_api_key
The db/api-server.js file is already configured for Supabase compatibility:
// Supabase connection configuration (already implemented)
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false,
max: 20, // Maximum number of clients in the pool
idleTimeoutMillis: 30000, // Close idle clients after 30 seconds
connectionTimeoutMillis: 2000, // Return an error after 2 seconds if connection could not be established
});Since the database and schema are already set up, you can test your connection immediately:
# Test database connection with shared Supabase
node -e "require('./db/api-server').pool.query('SELECT NOW()').then(r => console.log('Supabase connected:', r.rows[0])).catch(e => console.error('Connection failed:', e))"
# Start application
npm startNote: The shared database already contains all course data and required tables. No additional setup needed!
Connection Issues:
- Verify you have the correct shared database URL and password
- Check DATABASE_URL environment variable is set correctly
- Ensure SSL configuration is correct for production
- Contact team lead if connection issues persist
Schema Issues:
- The shared database already has the correct schema configured
- No need to modify table structures
- Check for case sensitivity in table/column names if custom queries fail
Performance Considerations:
- Use connection pooling URL for production (already configured in shared setup)
- Database is optimized for multiple concurrent users
- All course data is pre-loaded and regularly updated
When using Supabase for your database, you can deploy Course Cupid to Render for a fully cloud-hosted solution using their free tier and simple web interface.
- Supabase database setup completed (from previous section)
- Code pushed to GitHub repository
- Free Render account
Update server.js for Render compatibility:
// Change the port configuration to work with Render
const PORT = process.env.PORT || 3000; // Render automatically sets PORT
// Change the listen configuration
app.listen(PORT, '0.0.0.0', () => {
console.log(`Course Cupid server running on port ${PORT}`);
});Update package.json scripts:
{
"scripts": {
"start": "node server.js",
"build": "pip install -r requirements.txt"
},
"engines": {
"node": ">=16.0.0"
}
}# Commit your changes
git add .
git commit -m "Prepare for Render deployment"
git push origin supabase- Go to render.com
- Click "Get Started for Free"
- Sign up using your GitHub account (recommended for easy repo access)
- Verify your email if prompted
Step 1: Create New Web Service
- On your Render dashboard, click "New +"
- Select "Web Service"
- Click "Connect a repository"
- Choose your Course Cupid repository from the list
- Select the
supabasebranch
Step 2: Configure Build Settings
- Name:
course-cupid(or any name you prefer) - Build Command:
npm install && pip install -r requirements.txt - Start Command:
npm start - Plan: Select "Free" (perfect for development/testing)
Step 3: Add Environment Variables Click "Advanced" then add these environment variables:
| Key | Value |
|---|---|
NODE_ENV |
production |
DATABASE_URL |
Your Supabase connection string |
SESSION_SECRET |
A secure random string (min 32 characters) |
GEMINI_API_KEY |
Your Google Gemini API key |
GROQ_API_KEY |
Your Groq API key |
Example environment variables:
NODE_ENV=production
DATABASE_URL=postgresql://postgres.coursecupid:[PASSWORD]@aws-0-us-west-1.pooler.supabase.com:6543/postgres?sslmode=require
SESSION_SECRET=your_32_character_minimum_secure_session_secret_here
GEMINI_API_KEY=AIzaSyD...your_key_here
GROQ_API_KEY=gsk_...your_key_here
Note: Replace
[PASSWORD]with the actual database password provided by your team lead.
- Click "Create Web Service"
- Render will automatically:
- Clone your GitHub repository
- Install Node.js dependencies
- Install Python dependencies
- Start your application
- Wait for the build to complete (usually 2-5 minutes)
- Your app will be available at: https://repo-name.onrender.com
The shared Supabase database already contains all University of Otago course data. No additional data import is required!
If for any reason you need to verify or re-import data:
Option A: Verify Data Exists
# Check if course data is available
node -e "require('./db/api-server').pool.query('SELECT COUNT(*) FROM paper').then(r => console.log('Course count:', r.rows[0].count)).catch(e => console.error('Query failed:', e))"Option B: Contact Team If you encounter any data-related issues, contact the team rather than attempting to modify the shared database.
- Visit your Render app URL
- Test user registration and login
- Try the personality quiz
- Test course chat functionality
- Verify all features work correctly
Build Failures:
- Check that all dependencies are listed in
package.jsonandrequirements.txt - Verify Node.js version compatibility
- Review build logs in Render dashboard
Runtime Errors:
- Check environment variables are set correctly
- Verify Supabase database connection string
- Monitor application logs for error details
Free Tier Limitations:
- Service sleeps after 15 minutes of inactivity (takes ~30 seconds to wake up)
- 750 hours per month limit (about 1 month of continuous running)
When ready for production:
- Upgrade to Render's paid plans for 24/7 uptime
- Add custom domain
- Enable advanced monitoring and analytics
- Scale resources as needed
Course-Cupid/
├── frontend/ # Client-side application
│ ├── index.html # Landing page
│ ├── quiz.html # Personality quiz interface
│ ├── chat.html # Chat interface for courses/Cupid
│ ├── login.html # Authentication pages
│ ├── signup.html
│ ├── style.css # Main stylesheet
│ ├── app.js # Core frontend logic
│ ├── js/
│ │ ├── chat.js # Chat functionality
│ │ ├── quiz.js # Quiz logic and course cards
│ │ └── messages.js # Message handling
│ └── css/
│ └── chat.css # Chat-specific styles
│
├── db/ # Database layer
│ ├── api-server.js # Express API routes
│ ├── sql-tables.sql # Database schema
│ ├── schema.sql # Legacy schema
│ ├── importPapers.js # Course data import script
│ └── test-insert-data/ # Sample data for testing
│
├── webscrappers/ # Data collection tools
│ ├── paperscrapper.py # University of Otago course scraper
│ ├── papercode.py # Course code extraction
│ ├── papers_data.json # Scraped course information
│ └── paper_codes_100.txt # First-year course codes
│
├── server.js # Main Express server
├── google_course_matcher.py # AI course recommendation engine
├── course_matcher.py # Alternative matching system
├── package.json # Node.js dependencies
├── requirements.txt # Python dependencies
└── README.md # This file
- Web_User: User accounts and authentication
- Chat_Session: Chat sessions (both course and Cupid)
- Chat_Message: Individual messages within sessions
- Paper: Course information and metadata
- user_paper_matches: User course preferences/matches
- Users can have multiple chat sessions
- Sessions contain multiple messages
- Papers can be referenced in multiple sessions
- User matches link users to preferred courses
- Purpose: Generate semantic embeddings for course descriptions
- Process:
- Course descriptions vectorized using
gemini-embedding-001 - User quiz responses converted to query embeddings
- Cosine similarity matching for top 5 recommendations
- Course descriptions vectorized using
- File:
google_course_matcher.py
- Purpose: Create engaging course chatbots
- Process:
- Dynamic prompt generation incorporating course details
- Role-play as course "seeking" students (dating app metaphor)
- Contextual responses about course content and requirements
- Model:
meta-llama/llama-4-scout-17b-16e-instruct
POST /api/signup- User registrationPOST /api/login- User authenticationPOST /api/logout- Session terminationGET /api/me- Current user information
GET /api/papers- Paginated course listings with search/filterPOST /api/quiz-recommendations- AI-powered course matchingPOST /api/match- Save user course preferencesGET /api/my-matches- Retrieve user's matched courses
POST /api/chat/:identifier- Send message (course or Cupid)GET /api/chat/:identifier/messages- Retrieve chat historyPOST /api/chat-sessions- Create new Cupid chat sessionGET /api/chat-sessions- List user's chat sessionsDELETE /api/chat-sessions/:identifier- Remove chat session
- Source: Official University of Otago course catalog
- Scraping: Automated collection via
paperscrapper.py - Coverage: All first-year papers (100-level courses)
- Data Points: Course codes, titles, descriptions, subjects, prerequisites
- Format: JSON structure with course metadata
- Validation: Missing/incomplete course data filtered during import
- Updates: Manual re-scraping required for course changes
- Password Hashing: bcrypt with salt rounds
- Session Management: Express sessions with PostgreSQL storage
- CSRF Protection: Session-based validation
- Input Validation: Parameterized queries prevent SQL injection
- User Data: Minimal collection (username, email, preferences)
- Chat History: Stored locally, associated with user sessions
- API Keys: Environment variable configuration
- Course Data: Public university information only
- Familiar Interface: Dating app mechanics for intuitive navigation
- Gamification: Swipe-based course discovery
- Personalization: AI-driven recommendations based on user input
- Accessibility: Clean, responsive design with clear navigation
- Landing: Browse featured courses, create account
- Quiz: Answer personality/preference questions
- Recommendations: Swipe through AI-matched courses
- Chat: Interact with course personalities
- Matches: Review and manage selected courses
# Start development server
npm start
# Test database connection
node -e "require('./db/api-server').pool.query('SELECT NOW()').then(r => console.log(r.rows[0]))"# Re-scrape University of Otago courses
cd webscrappers
python paperscrapper.py
# Import updated course data
cd ..
node db/importPapers.js- Production Database: PostgreSQL with connection pooling
- Environment Variables: All sensitive data externalized
- API Rate Limits: Consider caching for AI API calls
- Static Assets: CDN for frontend resources
- Database Indexing: Optimize queries for user sessions and course searches
- Caching: Redis for session storage and frequent API responses
- Load Balancing: Multiple server instances for high traffic
- Monitoring: Application performance and API usage tracking
- Create feature branch from main
- Implement changes with appropriate testing
- Update documentation for new features
- Submit pull request with detailed description
- JavaScript: ESLint configuration provided
- Python: PEP 8 style guidelines
- SQL: Consistent naming conventions
- Comments: Document complex business logic
"Database connection failed"
- Verify PostgreSQL is running and accessible
- Check DATABASE_URL environment variable
- Ensure database exists and schema is created
- If using University of Otago provided PostgreSQL, ensure IP is within UoO Network.
"AI API errors"
- Confirm GEMINI_API_KEY and GROQ_API_KEY are set
- Check API key validity and quota limits
- Verify network connectivity to AI services
- Ensure API hosts are active
"Course data missing"
- Run
node db/importPapers.jsto populate database - Check
webscrappers/papers_data.jsonexists and is valid - Verify database permissions for data insertion
"Python script failures"
- Ensure virtual environment is activated
- Verify all Python dependencies installed
- Check python executable path in
spawncalls
- Advanced Filtering: Prerequisite tracking, timetable integration
- Social Features: Student reviews, peer recommendations
- Academic Planning: Multi-year course planning assistance
- Mobile App: Native iOS/Android applications
- Institution Expansion: Support for other universities
- AI Enhancement: Fine-tuned models for better course personalities
- Performance: Database optimization and caching strategies
- Testing: Comprehensive unit and integration test suites
This project is developed for educational purposes as part of COSC345 Software Engineering at the University of Otago.
- Katrina Hogg - Database Design & Backend Architecture
- Benjamin Hunt - Account Creation/Features and Backend Architecture
- Shyamalima Das - Frontend Development & User Experience
- Ned Redmond - Sentence Transformer AI integration and Quiz Features
- Matthew Greer - Web Scrapping/Data Processing and LLM Chatbot
Course Cupid - Making course selection as easy as finding your perfect match! 💘