An AI-powered quiz generation and evaluation microservice built with Node.js, Express, PostgreSQL, and Prisma.
- Features
- Tech Stack
- Getting Started
- API Documentation
- Caching Strategy
- Database Schema
- Docker Deployment
- Security Considerations
- Contributing
- License
- Acknowledgments
-
Authentication:
- User registration and login
- JWT token-based authentication
- Email verification for new accounts
- Secure HTTP-only cookies for token storage
-
Quiz Management:
- Generate quizzes using AI (Google Gemini API)
- Customize quizzes by grade, subject, difficulty, and number of questions
- Submit answers for AI evaluation with detailed feedback
- View quiz history with filtering options
- Get AI-generated hints for challenging questions
-
User Experience:
- Personalized dashboard with quiz statistics
- Email notifications with quiz results
- AI-generated improvement suggestions
- Performance tracking across subjects and time periods
-
Performance Optimization:
- Redis caching for faster response times
- Strategic caching of expensive operations
- Automated cache invalidation
- Background cache cleanup
- Backend: Node.js, Express
- Database: PostgreSQL with Prisma ORM
- Cache: Redis
- Authentication: JWT with HTTP-only cookies
- Email: Nodemailer
- AI: Google Gemini API
- Deployment: Docker, Docker Compose, Render
- Node.js (v18+)
- PostgreSQL
- Redis
- API key for Google Gemini
-
Clone the repository:
git clone https://github.com/yourusername/ai-quizzer.git cd ai-quizzer -
Install dependencies:
npm install
-
Set up environment variables:
cp .env.example .env
Then edit the
.envfile with your configuration. Required variables:# Server Configuration PORT=3000 NODE_ENV=development # Database Configuration DATABASE_URL=postgresql://postgres:password@localhost:5432/aiquizzer # JWT Configuration JWT_SECRET=your_jwt_secret_key JWT_EXPIRES_IN=1d # Redis Configuration REDIS_URL=redis://localhost:6379 # Email Configuration EMAIL_SERVICE=gmail EMAIL_USER=your_email@gmail.com EMAIL_PASSWORD=your_app_password # Google Gemini API GEMINI_API_KEY=your_gemini_api_key -
Generate Prisma client:
npx prisma generate
-
Run database migrations:
npx prisma migrate dev
Development mode:
npm run devProduction mode:
npm startBuild and run with Docker Compose:
docker-compose up -dThis will start both the application and PostgreSQL in containers.
The application is deployed on Render using a Docker image hosted on Docker Hub.
The public Docker image is available at harsh268/aiquizzer:latest.
To improve security by making your Docker image private:
-
Log in to Docker Hub:
- Go to Docker Hub and sign in with your account
- Navigate to your "aiquizzer" repository
-
Change repository visibility:
- Click on the "Settings" tab within your repository
- Scroll to find the "Visibility" section
- Change from "Public" to "Private"
- Save your changes
-
Update Render configuration for private image:
- Log in to your Render dashboard
- Go to your AI Quizzer service settings
- Enable "Private Registry"
- Enter your Docker Hub credentials
- Save the changes
Run the included PowerShell script:
.\push-docker-image.ps1The application is live at: https://aiquizzer-4qc3.onrender.com
You can visit the live application using the link above.
It is deployed on Render, so it may spin down due to inactivity. Your first request can take some time.
{
"username": "Harsh",
"email": "harshpatel17079@gmail.com",
"password": "Patel@123"
}The API is organized around RESTful principles. Below is a summary of the main endpoints:
-
POST /api/v1/auth/register: Register a new user
- Body:
{ "username": "user", "email": "user@example.com", "password": "password123" }
- Body:
-
GET /api/v1/auth/verify-email: Verify user email with token
- Query:
?token=verification_token
Currently, there is no frontend. You can set your app URL in the environment variables and match the path for the verification page, which should extract the token from params and call the backend API endpoint for verification.
- Query:
-
POST /api/v1/auth/login: Log in and receive authentication token
- Body:
{ "email": "user@example.com", "password": "password123" } - Response includes HTTP-only cookie with JWT token
- Body:
-
POST /api/v1/auth/logout: Log out and clear authentication cookie
-
POST /api/v1/auth/resend-verification: Resend email verification
-
GET /api/v1/users/profile: Get user profile information
-
GET /api/v1/users/stats: Get user quiz statistics
- Shows aggregated data on quiz performance
-
POST /api/v1/quizzes/generate: Generate a new quiz
- Body:
{ "grade": "5th", "subject": "Math", "numQuestions": 5, "maxScore": 100, "difficulty": "medium" }
- Body:
-
GET /api/v1/quizzes: Get all quizzes
- Supports filtering by grade, subject, date range, score range
- Supports pagination
-
GET /api/v1/quizzes/:id: Get a specific quiz by ID
-
POST /api/v1/quizzes/:id/submit: Submit answers for a quiz
- Body:
{ "answers": { "questionId1": "answer1", "questionId2": "answer2" }, "sendEmail": true } - Returns score, feedback, and improvement suggestions
- Body:
-
GET /api/v1/quizzes/history: Get quiz attempt history
- Supports filtering by grade, subject, score, date range
- Supports pagination
-
GET /api/v1/quizzes/attempts/:id: Get a specific quiz attempt
-
GET /api/v1/quizzes/:id/questions/:questionId/hint: Get an AI-generated hint for a specific question
The application implements a strategic caching approach to optimize performance:
-
Quiz Data:
- Cache Key:
quiz:{quizId} - TTL: 3600 seconds (1 hour)
- Invalidated when: A new attempt is submitted
- Cache Key:
-
User Profile:
- Cache Key:
user:profile:{userId} - TTL: 1800 seconds (30 minutes)
- Invalidated when: User creates a quiz or submits an attempt
- Cache Key:
-
User Statistics:
- Cache Key:
user:stats:{userId} - TTL: 900 seconds (15 minutes)
- Invalidated when: User creates a quiz or submits an attempt
- Cache Key:
-
Question Hints:
- Cache Key:
hint:{quizId}:{questionId} - TTL: 3600 seconds (1 hour)
- Automatic cleanup: Daily background job removes old hint caches
- Cache Key:
- Automatic Invalidation: Caches are automatically cleared when underlying data changes
- Background Cleanup: A scheduled task runs daily to clean up stale hint caches
- TTL Strategy: Different TTLs based on data volatility and access patterns
The database is managed using Prisma ORM, with the schema defined in prisma/schema.prisma. The main models include:
-
User: Stores user account information
- Authentication details
- Profile information
- Email verification status
-
Quiz: Stores quiz details
- Subject, grade, difficulty
- Questions array with various question types
- Maximum possible score
-
QuizAttempt: Stores quiz submissions
- User answers
- Score and feedback
- Timestamps for tracking progress
A Postman collection is included in the repository to help test the API:
- Import
postman_collection.jsoninto Postman - Set up the environment variables:
baseUrl: Set tohttps://aiquizzer-4qc3.onrender.comfor production orhttp://localhost:3000for local testingemail: Your email addresspassword: Your password
- Execute the requests in sequence:
- First register or login to get an authentication token
- The token will be automatically applied to subsequent requests
- Follow the testing guide in
postman_testing_guide.mdfor detailed steps
The AI Quizzer application implements several security features:
- JWT tokens with HTTP-only cookies
- Password hashing using bcrypt
- Email verification for new accounts
- Input validation for all API endpoints
- Use environment variables for sensitive information instead of hardcoding
- Follow the principle of least privilege in container configurations
- Consider making Docker Hub repository private for production use
- Use Docker secrets for managing sensitive credentials
- Google Gemini API for AI quiz generation
- Prisma for database ORM
- Express for the web framework
- Redis for caching
- Docker for containerization