Skip to content

Latest commit

 

History

History
666 lines (557 loc) · 21.9 KB

File metadata and controls

666 lines (557 loc) · 21.9 KB

StudySync AI — Documentation

Version: 0.0.0 | Stack: React 19 + Express + Prisma + Groq AI


Table of Contents

  1. Overview
  2. Architecture
  3. Tech Stack
  4. Database Schema
  5. API Reference
  6. Authentication & Security
  7. AI Integration
  8. Frontend Architecture
  9. Environment Variables
  10. Rate Limiting
  11. Development Setup
  12. Build & Deployment
  13. Project Structure

1. Overview

StudySync AI is a full-stack, enterprise-ready AI-powered productivity and learning platform. It integrates a smart study planner, AI-guided tutoring, assignment tracking, flashcard management, quiz generation, and learning analytics into one seamless workspace.

Key capabilities:

  • AI Tutor with conversational chat (Groq Llama 3.3 70B)
  • AI-powered quiz generator with configurable difficulty
  • AI-generated flashcards from any topic
  • AI-driven study suggestions
  • Assignment CRUD with priority and status tracking
  • Subject management with progress tracking
  • Rich note-taking with markdown support (starred, searchable)
  • Flashcard deck library with flip-card study mode
  • Interactive study planner with weekly calendar view
  • Analytics dashboard with charts and achievement badges
  • Dark-theme UI with responsive mobile layout

2. Architecture

Browser
   │
   ├── [SPA] React 19 + Vite (port 5173 dev / served by Express in prod)
   │        │
   │        ├── AuthContext (JWT in localStorage)
   │        ├── TanStack React Query (server state)
   │        └── Axios client (interceptors for auth header + 401 redirect)
   │
   └── [API] Express 4 (port 3000)
            │
            ├── Helmet (security headers)
            ├── CORS (restricted origins)
            ├── Morgan (HTTP logging)
            ├── Rate Limiters (multi-layer)
            ├── JWT Auth Middleware (/api/*)
            │
            ├── /auth/* ──► bcrypt + JWT ──► PostgreSQL (Prisma)
            ├── /api/*  ──► CRUD routes   ──► PostgreSQL (Prisma)
            └── /api/ai/* ──► Groq SDK    ──► Llama 3.3 70B
  • Monolithic but modular: Single Express server serves both the API and the SPA.
  • Dev mode: Vite dev server middleware for HMR.
  • Production mode: Serves compiled static assets from dist/.
  • SPA fallback: All unrecognized routes serve index.html.

3. Tech Stack

Frontend

Layer Technology
Framework React 19, TypeScript
Build Vite 6, esbuild
Routing React Router 7
Styling Tailwind CSS 4, clsx, tailwind-merge
Charts Recharts 3
Animations Motion 12 (Framer Motion successor)
Data Fetching TanStack React Query 5
HTTP Client Axios
Markdown react-markdown 10
Icons Lucide React
Notifications react-hot-toast 2
Dates date-fns 4

Backend

Layer Technology
Runtime Node.js 22, TypeScript, ESM
Framework Express 4
Database ORM Prisma 5 + PostgreSQL
Auth jsonwebtoken 9 (HS256), bcrypt 6
AI Groq SDK 1.3 (Llama 3.3 70B)
Security Helmet 8, express-rate-limit 8
Logging Morgan
Dev Runner tsx (TypeScript execution)

4. Database Schema

Entity-Relationship Diagram

User ──┬── Subject ──┬── Assignment
       │             └── Note
       ├── Assignment (direct FK)
       ├── Note (direct FK)
       └── Deck ──┬── Flashcard (cascade delete)

Models

User

Field Type Constraints
id UUID PK, default gen_random_uuid()
name VARCHAR(255) NOT NULL
email VARCHAR(255) UNIQUE, NOT NULL
password VARCHAR(255) NOT NULL (bcrypt hash)
createdAt TIMESTAMP default now()
updatedAt TIMESTAMP auto-updated

Subject

Field Type Constraints
id UUID PK
name VARCHAR(255) NOT NULL
code VARCHAR(100) NOT NULL
instructor VARCHAR(255) optional
progress INT default 0, min 0, max 100
userId UUID FK → User, NOT NULL

Assignment

Field Type Constraints
id UUID PK
title VARCHAR(500) NOT NULL
due TIMESTAMP NOT NULL
priority ENUM(High, Medium, Low) default Medium
status ENUM(pending, completed) default pending
subjectId UUID FK → Subject
userId UUID FK → User, NOT NULL

Note

Field Type Constraints
id UUID PK
title VARCHAR(500) NOT NULL
preview VARCHAR(500) NOT NULL
content TEXT optional
starred BOOLEAN default false
subjectId UUID FK → Subject
userId UUID FK → User, NOT NULL

Deck

Field Type Constraints
id UUID PK
name VARCHAR(500) NOT NULL
lastReviewed TIMESTAMP optional
mastery INT default 0, min 0, max 100
userId UUID FK → User, NOT NULL

Flashcard

Field Type Constraints
id UUID PK
front TEXT NOT NULL
back TEXT NOT NULL
deckId UUID FK → Deck, NOT NULL, cascade delete

5. API Reference

Authentication

All auth endpoints are behind authLimiter (20 req/15min per IP+email), authStrictLimiter (5 req/hr), and exponential authBackoffMiddleware.

Base path: /auth

POST /auth/register

Create a new account.

Field Type Validation
name string 1–100 chars, alphabetic + spaces/hyphens/apostrophes
email string Valid format, max 254 chars
password string 8–128 chars

Success (201):

{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "user": { "id": "uuid", "name": "Alice", "email": "alice@example.com" }
}

Errors: 400 (validation), 409 (email exists), 429 (rate limited)

POST /auth/login

Authenticate with existing credentials.

Field Type
email string
password string

Success (200): Same shape as register. Errors: 400 (validation), 401 (invalid credentials), 429 (rate limited)


Protected CRUD

All routes require Authorization: Bearer <token> header.

Rate limit: writeLimiter (30 req/min per user) on all mutations.

Subjects — /api/subjects

Method Path Action
GET /api/subjects List all subjects for the authenticated user
POST /api/subjects Create a subject
PUT /api/subjects/:id Update a subject (name, code, instructor, progress)
DELETE /api/subjects/:id Delete a subject

POST/PUT body:

{
  "name": "Data Structures",
  "code": "CS201",
  "instructor": "Dr. Smith",
  "progress": 50
}

Assignments — /api/assignments

Method Path Action
GET /api/assignments List all assignments (includes subject relation)
POST /api/assignments Create an assignment
PUT /api/assignments/:id Update an assignment
DELETE /api/assignments/:id Delete an assignment

POST/PUT body:

{
  "title": "Homework 3",
  "due": "2025-12-01T23:59:00Z",
  "priority": "High",
  "status": "pending",
  "subjectId": "uuid"
}

Notes — /api/notes

Method Path Action
GET /api/notes List all notes (includes subject relation)
POST /api/notes Create a note
PUT /api/notes/:id Update a note (title, preview, content, starred)
DELETE /api/notes/:id Delete a note

POST/PUT body:

{
  "title": "Binary Search Trees",
  "preview": "Key operations and traversal methods...",
  "content": "# BST\n\n## Operations\n...",
  "subjectId": "uuid",
  "starred": true
}

Decks — /api/decks

Method Path Action
GET /api/decks List all decks (includes embedded flashcards)
POST /api/decks Create a deck with optional cards
DELETE /api/decks/:id Delete a deck (cascades to cards)

POST body:

{
  "name": "CS Fundamentals",
  "cards": [
    { "front": "What is Big O?", "back": "Worst-case complexity measure" },
    { "front": "What is a stack?", "back": "LIFO data structure" }
  ]
}

AI Endpoints

Rate limit: aiLimiter (10 req/min per user).

All AI endpoints are at /api/ai/ and use Groq's llama-3.3-70b-versatile model.

POST /api/ai/chat — AI Tutor

{
  "message": "Explain how Dijkstra's algorithm works",
  "history": [
    { "role": "user", "content": "What is a graph?" },
    { "role": "assistant", "content": "A graph is..." }
  ]
}
  • message: max 5000 chars, required
  • history: last 5 messages max, each content max 2000 chars
  • Returns: { "response": "Dijkstra's algorithm..." } (markdown formatted)

POST /api/ai/suggestion — Study Suggestion

  • No input required.
  • Returns a 1-sentence AI-generated suggestion for a CS student.
  • Graceful fallback if GROQ_API_KEY is missing.

POST /api/ai/flashcards — Flashcards Generator

{ "topic": "Binary Search Trees" }
  • topic: max 500 chars
  • Returns 5 flashcards as a JSON array:
[
  { "front": "What is a BST?", "back": "A tree where left < root < right" }
]

POST /api/ai/quiz — Quiz Generator

{
  "topic": "Database Normalization",
  "difficulty": "Advanced",
  "questions": 10
}
  • topic: max 500 chars, required
  • difficulty: Beginner | Intermediate (default) | Advanced
  • questions: 1–20 (default 10)
  • Returns:
[
  {
    "question": "What is 3NF?",
    "options": ["...", "...", "...", "..."],
    "correctAnswer": 2
  }
]

6. Authentication & Security

Auth Flow

  1. User registers or logs in via /auth/*.
  2. Server validates credentials, returns JWT (HS256, 7-day expiry) with payload { id: userId }.
  3. Client stores token + user in localStorage.
  4. Axios interceptor attaches Authorization: Bearer <token> to all /api/* requests.
  5. On 401 response, Axios interceptor clears localStorage and redirects to /login.
  6. AuthContext checks localStorage on mount to restore session.

Security Measures

Measure Implementation
Password storage bcrypt with configurable cost (default 10)
JWT algorithm HS256 with algorithms: ['HS256'] verification
Input validation Type, length, regex patterns for name/email/UUID on server
User enumeration Generic "Invalid credentials" on login failure
Rate limiting 4 layers: general, auth, strict auth, exponential backoff
Security headers Helmet with custom CSP
CORS Restricted to configured origins
Error safety Stack traces suppressed in production
Request size 100kb JSON body limit

7. AI Integration

Provider

Groq Cloud with model llama-3.3-70b-versatile at temperature 0.7 (0.9 for suggestions).

Endpoints

All four AI endpoints (chat, suggestion, flashcards, quiz) are defined inline in server.ts.

Key Implementation Details

  • Chat history: Last 5 user/assistant messages sent as context.
  • Flashcard parsing: AI returns JSON wrapped in markdown code fences; parser strips fences and retries on parse failure.
  • Quiz parsing: AI returns JSON array directly; current implementation requires valid JSON output.
  • Graceful degradation: If GROQ_API_KEY env var is missing, the suggestion endpoint returns a static fallback message.
  • System prompt: "You are StudySync AI, an expert AI productivity assistant and learning tutor..."

8. Frontend Architecture

Routing (App.tsx)

Route Page Auth Required
/ Landing No
/login Login No
/register Register No
/forgot-password ForgotPassword No
/dashboard Dashboard Yes
/dashboard/ai-tutor AI Tutor Yes
/dashboard/quiz Quiz Generator Yes
/dashboard/planner Study Planner Yes
/dashboard/assignments Assignments Yes
/dashboard/analytics Analytics Yes
/dashboard/subjects Subjects Yes
/dashboard/flashcards Flashcards Yes
/dashboard/notes Notes Yes
/dashboard/settings Settings Yes
/dashboard/calendar Coming Soon Yes
/dashboard/homework Coming Soon Yes
/dashboard/exams Coming Soon Yes
/dashboard/notifications Coming Soon Yes

All dashboard pages are lazy-loaded with React.lazy + Suspense (spinner fallback) + ErrorBoundary.

State Management

State Type Mechanism
Auth React Context + localStorage
Server data TanStack React Query (auto cache invalidation)
UI state (modals, tabs, forms) Local useState
Profile/Notifications localStorage (no backend endpoint yet)

Key Components

Component Role
Layout App shell: Sidebar + Header + <Outlet>
Sidebar 15 nav items, mobile overlay, active highlighting
Header Search bar, notification bell, user avatar with gradient initials
ErrorBoundary Class-based catch with refresh/dashboard recovery

Styling

  • Dark theme: #0A0C10 (bg), #11141D (cards), #1F2937 (borders)
  • Accent: blue-500 primary, purple/emerald/rose/amber for variety
  • Utility: cn() from src/lib/utils.ts (clsx + tailwind-merge)
  • Accessibility: skip-to-content, aria labels, focus-visible, reduced-motion support

9. Environment Variables

Required

Variable Description
GROQ_API_KEY Groq Cloud API key
DATABASE_URL PostgreSQL connection string
JWT_SECRET JWT signing secret (min 32 characters)

Optional

Variable Default Description
APP_URL http://localhost:3000 Application base URL
PORT 3000 Server port
ALLOWED_ORIGINS http://localhost:3000 Comma-separated CORS origins
BCRYPT_ROUNDS 10 bcrypt salt rounds (min 10)
JWT_EXPIRES_IN 7d JWT expiry duration
DISABLE_HMR (unset) Set true to disable Vite HMR (AI Studio)

Rate Limit Overrides

Variable Default Description
GENERAL_LIMITER_WINDOW_MS 900000 (15 min) General rate limit window
GENERAL_LIMITER_MAX 100 General rate limit max requests
AUTH_LIMITER_WINDOW_MS 900000 (15 min) Auth rate limit window
AUTH_LIMITER_MAX 20 Auth rate limit max requests
AUTH_STRICT_LIMITER_WINDOW_MS 3600000 (1 hr) Strict auth limit window
AUTH_STRICT_LIMITER_MAX 5 Strict auth limit max requests
AI_LIMITER_WINDOW_MS 60000 (1 min) AI rate limit window
AI_LIMITER_MAX 10 AI rate limit max requests
WRITE_LIMITER_WINDOW_MS 60000 (1 min) Write rate limit window
WRITE_LIMITER_MAX 30 Write rate limit max requests

10. Rate Limiting

                  ┌──────────────────────┐
                  │   generalLimiter     │
                  │ 100 req / 15 min (IP)│
                  └────────┬─────────────┘
                           │
              ┌────────────┴────────────┐
              │                         │
     ┌────────┴────────┐       ┌────────┴────────┐
     │   /auth/*        │       │   /api/*        │
     │                  │       │   /api/ai/*     │
     └────────┬─────────┘       └────────┬────────┘
              │                          │
     ┌────────┴────────┐       ┌────────┴────────┐
     │  authLimiter    │       │   aiLimiter     │
     │  20/15min       │       │  10 req / 1 min │
     │  (IP + email)   │       │  (user ID)      │
     └────────┬────────┘       └─────────────────┘
              │
     ┌────────┴────────┐
     │ authStrictLim   │
     │  5 / 1 hr (IP)  │
     └────────┬────────┘
              │
     ┌────────┴────────┐
     │ authBackoffMid  │
     │ exponential:    │
     │ 30s→2m→8m→30m→2h│
     └─────────────────┘

Backoff entries are stored in-memory and auto-cleaned every 10 minutes. clearAuthFailureMiddleware resets backoff on successful login.


11. Development Setup

Prerequisites

  • Node.js 22+
  • PostgreSQL (local or remote)
  • Groq API key (free at console.groq.com)

Steps

# 1. Clone and enter the project
cd studysync-ai

# 2. Install dependencies
npm install

# 3. Copy environment file and fill in values
cp .env.example .env
# Edit .env: set GROQ_API_KEY, DATABASE_URL, JWT_SECRET

# 4. Run database migrations
npx prisma migrate dev --name init

# 5. Start dev server (runs both frontend + backend)
npm run dev

The app is now available at http://localhost:3000.

Useful Commands

Command Description
npm run dev Start development server (Vite HMR + Express)
npm run build Build frontend + bundle backend
npm run start Start production server
npm run lint TypeScript type-check (tsc --noEmit)
npm run preview Vite preview of built frontend
npx prisma studio Open Prisma Studio (DB GUI)
npx prisma migrate dev Apply schema changes to database

12. Build & Deployment

Build

npm run build

This runs:

  1. vite build — compiles React frontend to dist/
  2. esbuild server.ts — bundles Express backend to dist/server.cjs

Start Production

NODE_ENV=production npm run start

Deployment Checklist

  • Set NODE_ENV=production
  • Configure all env vars (especially JWT_SECRET with a strong 64+ char value)
  • Ensure PostgreSQL is accessible from the deployment environment
  • Run npx prisma migrate deploy to apply migrations
  • Set ALLOWED_ORIGINS to the production domain (or omit for same-origin)
  • Configure reverse proxy (nginx/Caddy) for SSL termination if needed
  • Adjust rate limits if deploying behind a proxy (use trust proxy)

Docker (manual — no Dockerfile included)

To containerize:

  1. Build the app: npm run build
  2. Create a Dockerfile with Node.js 22 base
  3. Copy dist/, package.json, node_modules/, prisma/
  4. Run: node dist/server.cjs

13. Project Structure

studysync-ai/
├── .env.example              # Environment variable template
├── .gitignore
├── index.html                # Vite SPA entry point
├── metadata.json             # AI Studio manifest
├── package.json
├── tsconfig.json
├── vite.config.ts
├── server.ts                 # Express server entry (routes + AI endpoints)
├── README.md
├── DOCUMENTATION.md          # This file
├── prisma/
│   └── schema.prisma         # Database schema (6 models)
├── assets/                   # Static assets
├── dist/                     # Build output (gitignored)
├── node_modules/             # Dependencies (gitignored)
└── src/
    ├── main.tsx              # React entry point
    ├── App.tsx               # Router + layout
    ├── index.css             # Tailwind + global styles
    ├── context/
    │   └── AuthContext.tsx   # Auth state management
    ├── lib/
    │   ├── api.ts            # Axios instance with interceptors
    │   └── utils.ts          # cn() utility (clsx + tailwind-merge)
    ├── components/
    │   ├── Layout.tsx        # App shell (Sidebar + Header + Outlet)
    │   ├── Sidebar.tsx       # Navigation sidebar
    │   ├── Header.tsx        # Top header bar
    │   └── ErrorBoundary.tsx # Error boundary wrapper
    ├── pages/
    │   ├── Landing.tsx       # Marketing / landing page
    │   ├── Login.tsx         # Login form
    │   ├── Register.tsx      # Registration form
    │   ├── ForgotPassword.tsx# Password reset (simulated)
    │   ├── Dashboard.tsx     # Main dashboard with stats + AI suggestion
    │   ├── AITutor.tsx       # AI chat interface
    │   ├── Quiz.tsx          # Quiz generator + taker
    │   ├── Planner.tsx       # Weekly study planner
    │   ├── Assignments.tsx   # Assignment CRUD
    │   ├── Analytics.tsx     # Charts + stats
    │   ├── Subjects.tsx      # Subject management
    │   ├── Flashcards.tsx    # Deck library + study mode
    │   ├── Notes.tsx         # Note-taking CRUD
    │   ├── Settings.tsx      # User settings (profile, appearance, security)
    │   └── NotFound.tsx      # 404 page
    └── server/
        ├── config.ts         # JWT config from env
        ├── auth.ts           # JWT authentication middleware
        ├── db.ts             # Prisma client singleton
        ├── rateLimit.ts      # Multi-layer rate limiting
        └── routes/
            ├── auth.ts       # Auth routes (register, login)
            └── api.ts        # Protected CRUD routes