Turn any document into smart flashcards with AI-powered extraction and spaced repetition.
AI Flashcard Gen is a study tool that extracts key concepts from your documents and generates ready-to-study flashcards. Upload PDFs, text or markdown files — the AI handles the rest.
Built for students, professionals and anyone who learns. Drop your material, get flashcards, study with spaced repetition.
| Feature | Description | |
|---|---|---|
| 🧠 | AI Extraction | Gemini 2.0 Flash analyzes your documents and generates question/answer pairs automatically |
| 🔁 | Spaced Repetition | SM-2 algorithm schedules optimal review intervals — study what you need, when you need it |
| 📇 | Single Card View | Navigate flashcards one at a time with flip animations, mastery tracking and keyboard shortcuts |
| 🖼️ | Gallery View | Grid layout to browse all cards at a glance, with inline flip and sorting by category, difficulty or status |
| 🌐 | Concept Map | Interactive force-directed graph showing relationships between concepts and categories |
| 🔈 | Text-to-Speech | Listen to questions and answers with auto language detection (English/Spanish) |
| 📁 | Multi-file Upload | Drag & drop multiple files at once — PDF, TXT and Markdown supported |
| 📊 | Study Stats | Track your progress with mastery counts, due cards and review streaks |
| 🌓 | Dark Mode | Full light/dark theme support |
| 💾 | Local Storage | Your flashcards persist in the browser — no account needed |
| 🛡️ | Smart Fallback | If AI generation fails, a heuristic parser extracts cards from text structure |
| Layer | Technology |
|---|---|
| Framework | Next.js 16 with Turbopack |
| Frontend | React 19, Tailwind CSS 4 |
| State | Zustand 5 |
| AI | Google Gemini 2.0 Flash (@google/genai) |
| pdf-parse with raw bytes fallback | |
| Audio | Web Speech API (native, zero dependencies) |
| Language | TypeScript 5 |
- Node.js 18+ installed (download)
- Google Gemini API key — free at Google AI Studio
git clone https://github.com/uxdreaming/AI-Flashcard-Gen.git
cd AI-Flashcard-Gennpm installcp .env.example .env.localOpen .env.local and add your Gemini API key:
GEMINI_API_KEY=your_api_key_herenpm run devNavigate to http://localhost:3000 and start uploading your study material.
| Format | Extension | Details |
|---|---|---|
.pdf |
Text extraction with raw bytes fallback for complex files | |
| 📝 Plain text | .txt |
Direct text processing |
| 📑 Markdown | .md |
Supports headers, lists, tables and structured content |
Max file size: 10 MB per file. Multiple files can be uploaded at once.
A quick walkthrough of the full experience, from uploading your first file to mastering your deck.
Drop one or more files into the upload zone (or click to browse). PDF, TXT and Markdown are supported. You can also hit Try demo to skip this step and explore with a pre-built deck.
Once your files are loaded, pick a difficulty (Basic, Intermediate, Advanced) and how many cards you want (5 to 30). Hit Generate — the AI reads your documents, identifies the key concepts and creates question/answer pairs organized by category.
This is the main study mode. The sidebar lists all your cards with category colors and mastery dots. Click any card to jump to it, or use the arrow keys to navigate. Click the card to flip it and reveal the answer.
After flipping a card, rate how well you knew the answer:
- Again — You didn't know it. The card resets and comes back soon.
- Good — You got it but needed effort. The interval grows moderately.
- Easy — You knew it instantly. The card is pushed further into the future.
This drives the SM-2 spaced repetition algorithm — cards you struggle with appear more often, cards you master fade into longer review cycles.
The Study Now button in the sidebar filters your deck to only show cards that are due for review right now. A red badge tells you how many are waiting. When you've reviewed them all, you'll see "All caught up!" with a countdown to your next review.
Switch to the grid icon in the sidebar to see all your cards at a glance. Each mini-card shows the question, category color, and difficulty tag. Click any card to jump back to single view and study it.
The graph icon opens an interactive force-directed map. Category nodes are large circles connected to their individual cards. Drag nodes around to explore how your topics relate. Click any card node to jump to it.
Click the speaker icon on any card to hear it read aloud. The app auto-detects whether the text is in English or Spanish and picks the right voice. Turn on Auto-read in the sidebar to have every card read automatically as you navigate — great for hands-free review or auditory learning.
- Filter by category, mastery status (new / learning / mastered) or difficulty from the sidebar
- Edit any card inline — click the pencil icon to change the question, answer or category
- Delete cards you don't need
- Export your deck as CSV or Anki-compatible format from the export menu
Click Save to persist your deck in the browser's local storage. Next time you open the app, your cards, mastery levels and review schedules are right where you left them — no account needed.
Document Upload → Text Extraction → AI Analysis → Flashcard Generation
.pdf pdf-parse Gemini 2.0 Q&A pairs with
.txt raw fallback Flash categories &
.md difficulty
- Upload — Drag & drop or browse for files (PDF, TXT, MD)
- Configure — Choose difficulty level (Basic / Intermediate / Advanced) and card count (5-30)
- Generate — AI extracts key concepts and creates flashcards
- Study — Review cards in single view, gallery or concept map with spaced repetition
- Listen — Use text-to-speech to hear questions and answers
- Track — Monitor mastery progress with "Study Now" for due reviews
One of the most technically interesting features is Read Mode — a text-to-speech system that automatically detects whether a flashcard is in English or Spanish and reads it aloud in the correct language.
The Web Speech API requires you to specify a language code (en-US, es-ES) before speaking. If you set the wrong language, the speech engine mispronounces everything — an English voice reading Spanish sounds broken, and vice versa. Since flashcards can contain content in either language (or mixed), the system needs to figure out the language on its own, per card, in real time.
Instead of using an external library or API call, the solution uses a regex-based heuristic that checks for Spanish-specific patterns:
const spanishPattern = /[áéíóúñ¿¡]|(\b(el|la|los|las|de|del|en|es|un|una|que|por|con|para|como|más|pero|este|esta)\b)/i;This catches two signals:
- Diacritical characters —
á,é,í,ó,ú,ñ,¿,¡are strong indicators of Spanish text - High-frequency words — Articles (
el,la,los,las), prepositions (de,en,por,con,para) and common words (que,más,pero) that appear in virtually any Spanish sentence
If either pattern matches, the card is treated as Spanish (es-ES). Otherwise it defaults to English (en-US). This zero-dependency approach runs instantly and handles the vast majority of real-world study content correctly.
After detecting the language, the system queries the browser's available voices and picks one that matches:
const voices = window.speechSynthesis.getVoices();
const matchingVoice = voices.find((v) => v.lang.startsWith(lang));This is important because different browsers and operating systems ship different voice sets. On Chrome, Google's voices are available. On macOS, Apple's system voices are used. The code gracefully falls back to the default voice if no match is found.
Beyond manual playback (clicking the speaker icon), there's an Auto-Read toggle in the sidebar that automatically reads each question aloud as you navigate between cards. This creates a hands-free study experience — useful for auditory learners or when reviewing cards away from the screen.
The auto-read triggers on card index changes but only in single-card view:
useEffect(() => {
if (autoRead && activeCards[currentIndex] && viewMode === "single") {
speak(activeCards[currentIndex].question);
}
}, [currentIndex, autoRead, viewMode]);The audio system is structured as a custom React hook (useAudio) that exposes a clean API:
| Export | Purpose |
|---|---|
speak(text) |
Detect language, select voice, and read text aloud |
stop() |
Cancel any active speech |
speaking |
Boolean state for UI feedback (icon highlighting) |
autoRead |
Whether auto-read mode is enabled |
toggleAutoRead() |
Toggle auto-read on/off |
This hook is consumed by FlashcardList (auto-read logic) and passed down to FlashcardItem (manual playback buttons on both the question and answer sides of each card).
- No external dependencies — The entire feature runs on the native Web Speech API, which means zero bundle size impact but also dealing with browser inconsistencies in voice availability and timing
- Per-card language switching — Each card can be a different language, so detection happens at speak time, not once globally
- Speech lifecycle management — Canceling previous speech before starting new speech, cleaning up on unmount, and syncing the
speakingstate across components required careful ref and effect management - Cross-browser voice availability —
getVoices()returns an empty array on first call in some browsers (it loads asynchronously), which the code handles by falling back gracefully
AI-Flashcard-Gen/
├── src/
│ ├── app/
│ │ ├── api/generate/ # API route for flashcard generation
│ │ ├── layout.tsx # Root layout with Geist fonts
│ │ ├── page.tsx # Landing page & study mode entry
│ │ └── globals.css # Global styles & animations
│ ├── components/
│ │ ├── FlashcardItem.tsx # Single card with flip animation
│ │ ├── FlashcardList.tsx # Main study interface & sidebar
│ │ ├── GalleryView.tsx # Grid view with mini-cards
│ │ ├── ConceptMap.tsx # Force-directed concept graph
│ │ ├── FileUpload.tsx # Drag & drop upload zone
│ │ ├── LoadingIndicator.tsx
│ │ ├── StudyStats.tsx # Progress statistics
│ │ └── ThemeToggle.tsx # Dark/light mode switch
│ ├── hooks/
│ │ └── useAudio.ts # Text-to-speech hook
│ ├── lib/
│ │ ├── gemini.ts # Gemini AI integration
│ │ ├── extractText.ts # PDF & text extraction
│ │ ├── parseFlashcards.ts # Heuristic fallback parser
│ │ ├── spacedRepetition.ts # SM-2 algorithm
│ │ ├── categoryColors.ts # Muted color palette
│ │ └── exportCards.ts # CSV/JSON export
│ ├── store/
│ │ └── useFlashcardStore.ts # Zustand state management
│ └── types/
│ └── flashcard.ts # TypeScript interfaces
├── docs/ # Screenshots & assets
├── .env.example # Environment template
└── package.json
| Command | Description |
|---|---|
npm run dev |
Start development server with Turbopack |
npm run build |
Production build |
npm run start |
Start production server |
npm run lint |
Run ESLint |
| Feature | |
|---|---|
| ✅ | Text extraction from PDF with raw bytes fallback |
| ✅ | AI flashcard generation with Gemini 2.0 Flash |
| ✅ | Support for PDF, TXT and Markdown files |
| ✅ | Drag & drop multi-file upload with validation |
| ✅ | Difficulty selector (Basic / Intermediate / Advanced) |
| ✅ | Flashcard count selector (5, 10, 15, 20, 30) |
| ✅ | Single card view with 3D flip animation |
| ✅ | Gallery view with mini-card grid and inline flip |
| ✅ | Interactive concept map with force-directed graph |
| ✅ | Text-to-speech with auto language detection |
| ✅ | SM-2 spaced repetition algorithm |
| ✅ | "Study Now" mode filtering due cards |
| ✅ | Mastery tracking (Again / Good / Easy) |
| ✅ | Category, status and difficulty filters |
| ✅ | CSV and JSON export |
| ✅ | Dark mode with system detection |
| ✅ | Local storage persistence |
| ✅ | Heuristic fallback parser when AI is unavailable |
| ✅ | Rate limiting on API endpoint |
| ✅ | Keyboard navigation between cards |
| ✅ | Responsive design (mobile + desktop) |
| ✅ | Clean visual design with muted color palette |
MIT
Built with 💙 by uxdreaming




