Spaces:
Runtime error
Learning Journey: Building a Project-Based Learning Platform
This document serves as a comprehensive guide to the architectural changes and new technologies introduced in this project. We've shifted from a traditional MongoDB setup to a high-performance, structured backend using PostgreSQL, Prisma, and Redis.
π The Core Tech Stack
1. PostgreSQL (The Database)
What it is: A powerful, open-source Relational Database (RDBMS). Why we used it: Unlike MongoDB (which is NoSQL/Document-based), PostgreSQL excels at handling complex relationships between data (e.g., a User has many Projects, a Project has many Milestones). It ensures "Data Integrity" through schemas and constraints.
2. Prisma ORM (The Bridge)
What it is: Prisma is a next-generation Node.js and TypeScript ORM (Object-Relational Mapper). Why we used it:
- Type Safety: It generates a TypeScript client based on your schema. If you try to query a field that doesn't exist, your code won't compile.
- Auto-migrations: Instead of writing manual SQL, we define our models in
schema.prisma, and Prisma handles the database structure. - Visual Exploration: You can use
npx prisma studioto view and edit your data in a browser.
3. Redis (The Speedster)
What it is: An in-memory data structure store, used as a database, cache, and message broker. We use the ioredis library, which is the industry standard for robust Redis connections in Node.js.
How to get the URL:
The connection URL is stored in the REDIS_URL environment variable.
Local Development: Usually
redis://localhost:6379.Production: A secure URL provided by your hosting provider (e.g., Upstash, Redis Labs).
Ephemeral Data: For things like OTP (One-Time Passwords) that expire quickly, writing to a disk-based database is slow and creates "trash" data.
Performance: Redis stores data in RAM, making it incredibly fast for short-term storage.
Caching: We use Redis to cache the global Leaderboard (
leaderboard:top20). Instead of querying the database every time someone views the leaderboard, we serve the result in milliseconds from memory.
π Step-by-Step Implementation
Phase 1: Authentication & Identity
Goal: Securely manage user access and state.
- User Schema: We defined a
Usermodel with roles (STUDENT,ADMIN,CONTRIBUTOR) and skill levels. - Argon2 Hashing: Instead of plain text, we use
argon2for industry-standard password hashing. - JWT Strategy: Upon login, we generate a JSON Web Token (JWT) with a 7-day expiry. This token is stored in an
httpOnlycookie for security against XSS. - OTP via Redis: For "Forgot Password", we generate a 6-digit OTP, store it in Redis with a 1-hour TTL (
redis.setex), and email it usingnodemailer. This avoids database bloat for temporary data.
Phase 2: The Project Engine
Goal: Create a structured environment for project-based learning.
- Hierarchical Data: Projects are linked to multiple
ProjectMilestonerecords. Each milestone acts as a step in the learning journey. - Multi-Mode Progression: Users can choose between
GUIDED,STANDARD, orHARDCOREmodes. This is stored in theUserProjectjoin table. - Milestone Tracking: As users complete steps, we create
UserMilestonerecords. This allows the frontend to show a granular progress bar. - Contextual Metadata: Projects store
technologies,categories, andlearningObjectivesas arrays, enabling powerful filtering in thegetProjectsAPI.
Phase 3: AI Mentorship (Gemini 1.5)
Goal: Provide 24/7 personalized guidance without giving away answers.
- Context Injection: Every chat request to
/api/ai/chatfetches the current project's title, description, and all milestones. - Mode-Specific Prompts:
- Guided: AI is instructed to be helpful and provide small code snippets.
- Hardcore: AI is instructed to be brief and only provide conceptual hints.
- Chat Persistence: Every message is saved to the
ChatMessagetable, allowing the AI to maintain a conversation history even if the user refreshes the page. - On-Demand Hints: The
/api/ai/hintendpoint uses Gemini to generate a new hint based on the milestone's description and existing hints, ensuring students don't get stuck.
Phase 4: Gamification & Performance
Goal: Keep users motivated through progress visualization.
- XP Awarding: Completing milestones triggers the
awardXPutility, which increments the user'sxpfield in PostgreSQL. - Redis-Backed Leaderboard:
- To avoid heavy
ORDER BY xp DESCqueries on every page load, we cache the Top 20 users in Redis (leaderboard:top20). - Cache Invalidation: Whenever someone earns XP, we run
redis.del(LEADERBOARD_CACHE_KEY)to ensure the next viewer sees updated rankings.
- To avoid heavy
- Achievement Engine: We use the
UserAchievementmodel to link users to specific milestones (e.g., "First Project Completed").
Phase 5: Community & Collaboration
Goal: Enable peer-to-peer learning and social validation.
- Submissions & Feedback: Users "publish" their work via
Submission. This records their repo URL and AI-generated feedback. - Voting System: A
Votemodel (Up/Down) allows the community to surface high-quality solutions. - Discussion Threads: The
Commentmodel supports nested conversations on projects and submissions. - Team Formation: The
TeamandTeamMembermodels allow users to group up, sharing the same project progress and milestones.
Phase 6: Automated Code Review
Goal: Bridge the gap between coding and professional feedback.
- GitHub API Integration: When a user submits a repo URL, the backend uses
axiosto hit the GitHub API, fetching repo metadata (stars, description, primary language). - AI Code Analysis: We send the repository context to Gemini to act as a "Senior Developer," providing constructive feedback on project structure and best practices.
- Scoring Logic: A simulated scoring system provides immediate gratification and a baseline for improvement.
π‘ New Concepts to Master
1. Migrations
When you change the schema.prisma file, you need to sync it with your database.
- Command:
npx prisma migrate dev --name init - This creates a SQL file and updates your database structure.
2. Global Error Handling
We moved away from individual try/catch blocks sending responses. Instead, we use a central middleware:
- Controller catches error.
- Calls
next(error). middlewares/errorHandler.tsformats the error and sends a consistent JSON response.
3. Progressive Scaffolding
The "Tutorial Hell" killer. Instead of a single "Build this" instruction, projects are broken into ProjectMilestone. Each milestone has its own:
- Validation Criteria: What the user must achieve.
- Hints: Step-by-step clues.
- AI Context: The AI Guide specifically focuses on the current milestone number.
4. Aggregations & Analytics
We use Prisma's groupBy and _count features to generate user and admin dashboards (e.g., counting total submissions, calculating project completion rates).
π Useful Commands for Learning
npx prisma generate: Re-generates the TypeScript types (run this after changing the schema).npx prisma studio: Opens a GUI to see your PostgreSQL data.npx tsc --noEmit: Checks your whole project for TypeScript errors.
π― Next Steps for You
- Explore the Schema: Look at
prisma/schema.prismaand try adding a new field (liketwitterHandleto the User model). - Check the Logs: Run the server and watch the terminal to see how Redis connects.
- Test an API: Use Postman or Insomnia to hit
POST /api/ai/chatand see how the AI responds based on the project context.
π― Next Steps for You
- Explore the Schema: Look at
prisma/schema.prismaand try adding a new field (liketwitterHandleto the User model). - Check the Logs: Run the server and watch the terminal.
- Test an API: Use Postman or Insomnia to hit
POST /api/ai/chatand see how the AI responds based on the project context.
π How to Start the Project
Follow these steps to get everything running correctly:
1. Sync the Database
Ensure your Prisma client and database schema are in sync:
npx prisma generate
npx prisma migrate dev
2. Seed the Database (Optional)
If you need initial data:
npm run seed
3. Start the Backend Server
Now you can start your development server:
npm run dev