Technical Case Study · AI & Agents
FlashAI
Spaced-repetition flashcard app
Solves the "PDF graveyard" problem by transforming uploaded lecture PDFs into 15–20 exam-quality flashcards in seconds. Streams NDJSON responses from Groq across 5 cognitive card types, isolates per-user SuperMemo SM-2 review schedules, and supports 1-click community deck cloning, live learner presence, and 6-digit email OTP cross-device sync.
Problem Statement
Passive re-reading of technical notes leads to rapid memory decay, while manual flashcard creation is tedious and standard LLM wrappers block the UI waiting for full JSON payloads.
Deterministic Architecture Advantage
Streams flashcards in sub-second NDJSON chunks from Groq LLaMA-3.3-70B and schedules long-term reviews using a deterministic SuperMemo SM-2 algorithm updating card easiness factor (EF >= 1.3), repetition count, and day intervals.
Execution Pipeline & System Topology
PDF Extraction & Rate Gate
Validates MIME/size bounds, extracts text via pdf-parse, and checks sliding-window rate limiters.
Groq NDJSON Streamer
Streams 5 cognitive card types line-by-line via ReadableStream with sanitizeJsonLine recovery.
Isolated SM-2 Scheduler
Computes deterministic Ease Factor and interval updates per user; resets state on community deck clones.
Neon PostgreSQL & OTP Sync
Persists Users, VerificationCodes, Decks, Flashcards, XP streaks, and live leaderboard podiums.
Verification & Engineering Highlights
- Built for the Cuemath AI Builder campus placement challenge: features hybrid guest onboarding + 6-digit CSPRNG email OTP cross-device account linking with 5-attempt brute-force lockout.
- Enforces a 5-category cognitive taxonomy per PDF: Definition, Reasoning ("why/how"), Common Misconception, Worked Example, and Edge Case.
- Includes Community Deck Library with 1-click deck cloning (resetting SM-2 state per learner), 45-second sliding-window live learner presence heartbeat, and 244 passing Vitest tests.
export interface SM2State {
interval: number; // Days until next review
repetitions: number; // Consecutive successful recalls
easeFactor: number; // SuperMemo EF (clamped >= 1.3)
}
export function calculateSM2(quality: 0 | 1 | 2 | 3 | 4 | 5, prev: SM2State): SM2State {
let { interval, repetitions, easeFactor } = prev;
if (quality >= 3) {
if (repetitions === 0) interval = 1;
else if (repetitions === 1) interval = 6;
else interval = Math.round(interval * easeFactor);
repetitions += 1;
} else {
repetitions = 0;
interval = 1;
}
const delta = 0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02);
easeFactor = Math.max(1.3, Number((easeFactor + delta).toFixed(2)));
return { interval, repetitions, easeFactor };
}