Personal Project
exammable.
Built a production-ready SaaS learning platform from scratch with AI-powered content generation, spaced repetition, and Stripe monetisation
Year
2026
Role
Sole Developer
Duration
24 weeks
Read Time
5 min read

Exammable
A full-stack SaaS learning platform that turns any source material — PDFs, slides, YouTube videos, or plain text — into AI-generated flashcards, then schedules reviews using spaced repetition science to maximise long-term retention.
Project Overview
Students spend hours manually creating study materials, only to review them inefficiently. Exammable solves both problems: it uses GPT-4 to generate high-quality questions from any document format, then applies the SM-2 spaced repetition algorithm to schedule reviews at scientifically optimal intervals. The platform targets university students and self-learners who want to study smarter, not harder.
What makes this project technically interesting is the multi-pass AI validation pipeline — generated questions go through a second LLM pass that detects factual errors, ambiguous phrasing, and unsupported claims before they ever reach the user.
The Challenge
- Multi-format document processing: Users upload PDFs, PowerPoints, Word docs, or paste YouTube URLs. Each format requires a different extraction pipeline (pdfjs-dist, JSZip XML parsing, mammoth, transcript APIs), all feeding into a unified generation flow with intelligent text chunking.
- AI quality at scale: Raw LLM output isn't reliable enough for study material. A single hallucinated answer can teach users the wrong thing. The system needed a validation layer that catches errors without blocking the generation flow.
- Instant-feeling auth on a token-based system: JWT access tokens expire every 15 minutes for security, but users shouldn't see loading screens every time they open the app. Solving this required session caching, silent background refresh, and tab-visibility detection.
Technical Architecture
The system follows a layered architecture: controllers handle HTTP concerns, services contain business logic, and middleware manages cross-cutting concerns like auth, rate limiting, and subscription gating. The database uses 24 Prisma models covering users, content, learning state, payments, gamification, and security audit trails.
The AI generation pipeline is the most architecturally interesting piece — it chunks large documents, distributes question generation across chunks, validates answers with a second LLM pass, and caches results to prevent duplicate work.
// Second-pass AI validation catches errors before users see them
export interface AnswerValidationResult {
questionIndex: number;
isValid: boolean;
confidence: number; // 0-100
issues: AnswerIssue[];
suggestedFix?: {
answer?: string;
question?: string;
explanation?: string;
};
}
export interface AnswerIssue {
type: 'factual_error' | 'calculation_error' | 'incomplete_question'
| 'logical_error' | 'ambiguous' | 'unsupported_claim';
severity: 'critical' | 'major' | 'minor';
description: string;
}
// Validates in batches, attempts fixes for borderline content,
// and tracks metrics on validation accuracy
async validateBatch(
questions: Question[],
sourceText: string
): Promise<AnswerValidationBatchResult> {
const validatedQuestions: Question[] = [];
let fixed = 0;
for (let i = 0; i < questions.length; i += this.config.batchSize) {
const batch = questions.slice(i, i + this.config.batchSize);
const validations = await this.validate(batch, sourceText);
validations.forEach((validation, index) => {
if (validation.isValid) {
validatedQuestions.push(batch[index]);
} else if (this.config.attemptFixes && validation.suggestedFix) {
validatedQuestions.push({ ...batch[index], ...validation.suggestedFix });
fixed++;
}
});
}
return { validatedQuestions, stats: { fixed, total: questions.length } };
}
Key Features
1. AI-Powered Multi-Source Generation
What it does: Upload a PDF, PowerPoint, Word document, paste a YouTube URL, or type a topic — the system extracts text, chunks it intelligently, generates questions via GPT-4, then validates every answer with a second LLM pass. Users get study-ready flashcards in seconds, with confidence scores on each question's accuracy.
2. Spaced Repetition with Mastery Scoring
What it does: Implements the SM-2 algorithm to schedule reviews at optimal intervals — 1 day after first learning, 6 days after that, then progressively longer gaps scaled by a per-card difficulty factor. Each card tracks a 0-100 mastery score, and failed reviews reset the interval without losing the accumulated difficulty data.
3. Multiple Study Modes
What it does: Users choose how to study: timed multiple-choice quizzes, short-answer with fuzzy matching, active recall with self-grading, or pure SRS review mode. Each mode feeds back into the spaced repetition system, so any study session improves future scheduling.
4. Subscription Monetisation
What it does: Three-tier Stripe integration (Free / Pro at $4/mo / Unlimited at $7/mo) with real-time feature gating. The SubscriptionContext checks limits before every action — creating sets, generating AI content, exporting PDFs — and shows contextual upgrade prompts when users hit their tier's ceiling.
5. Gamification & Engagement
What it does: Badge system, study streaks, XP-based levelling, and achievement tracking keep users coming back. Stats are surfaced throughout the app — on the home page, profile, and a dedicated gamification dashboard — creating feedback loops that reinforce consistent study habits.
Results & Impact
Lessons Learned
What Went Well
- Layered service architecture kept the codebase navigable at scale — 18 controllers and 12 services stayed cleanly separated, making it easy to add features without touching unrelated code
- Second-pass AI validation was worth the extra API cost — catching factual errors before they reach users is critical for a learning tool where wrong answers actively harm the user
- Session caching for auth eliminated the loading-screen-on-every-visit problem that plagues many JWT-based SPAs, making the app feel instant
What I'd Do Differently
- Database migrations discipline from day one — using prisma db push instead of prisma migrate dev broke production twice before I locked it down. Schema changes without migration files are invisible landmines
- Start with fewer subscription tiers — three tiers added complexity to feature gating without clear user demand. Two tiers (free + paid) would have shipped faster and been easier to test
Interested in similar results?
Let's discuss how I can help bring your project to life with the same attention to detail.