A lightweight, offline-first Progressive Web App (PWA) for tracking LeetCode problem reviews using spaced repetition. Built with clean architecture principles and designed for deliberate practice.
- ✅ Spaced Repetition Algorithm - Smart scheduling based on difficulty
- ✅ Offline-First - Works without internet using IndexedDB
- ✅ Autocomplete Search - Quickly find and review existing problems
- ✅ Review Queue - Prioritized by due date with overdue indicators
- ✅ Progressive Web App - Install on iPhone, Mac, or any device
- ✅ Auto-Archive - Problems automatically archive after 3 successful reviews
- ✅ Clean Architecture - Deep modules with information hiding
- Framework: Next.js 14 (App Router) + TypeScript
- Styling: Tailwind CSS
- Storage: Dexie.js (IndexedDB wrapper)
- Deployment: Vercel (recommended)
This app follows John Ousterhout's Philosophy of Software Design with:
src/domain/
├── SRSScheduler.ts # Handles all scheduling logic
├── ProblemRepository.ts # Hides IndexedDB complexity
└── ReviewQueue.ts # Manages review queue sorting
UI Components (Thin)
↓
Application Services (Thin orchestrator)
↓
Domain Modules (Deep - business logic)
↓
Storage Adapter (Deep - hides IndexedDB)
- Easy: 90 days (essentially archived)
- Medium: 7 days
- Hard: 3 days
- Didn't Get: 1 day
After each successful review, intervals multiply:
- Review 1: Base interval
- Review 2: Base × 2
- Review 3: Base × 2
- Review 4+: Base × 3
Max interval: 90 days Auto-archive: After 3 successful reviews (EASY or MEDIUM)
- Node.js 18+
- npm or yarn
- Extract the ZIP file
unzip codereps.zip
cd codereps- Install dependencies
npm install- Run locally
npm run devOpen http://localhost:3000 in your browser.
- Install Vercel CLI
npm install -g vercel- Deploy
vercelFollow the prompts. Vercel will:
- Create a GitHub repository for you
- Deploy your app
- Give you a live URL
- Auto-deploy on every push
- Push to GitHub
git init
git add .
git commit -m "Initial commit"
git remote add origin <your-github-repo-url>
git push -u origin main- Connect to Vercel
- Go to vercel.com
- Import your GitHub repository
- Click "Deploy"
That's it! Your app will be live at https://your-app.vercel.app
- Open the app in Safari
- Tap the Share button
- Tap "Add to Home Screen"
- Tap "Add"
- Open the app in Chrome/Edge
- Click the install icon in the address bar
- Click "Install"
- Open the app in Chrome
- Tap the three dots menu
- Tap "Add to Home Screen"
- Enter problem name (autocomplete will suggest existing problems)
- Optionally enter problem number
- Select review date (defaults to today)
- Click a difficulty button:
- Easy: Won't review again (or 90 days)
- Medium: Review in 7 days
- Hard: Review in 3 days
- Didn't Get: Review tomorrow
- Today's Reviews section shows all due/overdue problems
- First 3 reviews are always visible
- Click "Show X more reviews" to see all
- Click problem name to open on LeetCode (if number is provided)
- Use Archive to manually archive a problem
- Use Delete to permanently remove a problem
- Archive: Remove from active reviews (can unarchive later)
- Auto-archive: Happens after 3 successful reviews
- Delete: Permanently remove (cannot undo)
codereps/
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── layout.tsx
│ │ ├── page.tsx
│ │ └── globals.css
│ │
│ ├── domain/ # Domain layer (deep modules)
│ │ ├── models/
│ │ │ └── Problem.ts
│ │ ├── SRSScheduler.ts
│ │ ├── ProblemRepository.ts
│ │ └── ReviewQueue.ts
│ │
│ ├── storage/ # Storage layer
│ │ └── IndexedDBAdapter.ts
│ │
│ ├── services/ # Application services
│ │ └── ReviewService.ts
│ │
│ └── components/ # UI components
│ ├── ProblemInput.tsx
│ ├── ReviewList.tsx
│ └── Stats.tsx
│
├── public/ # Static assets
│ └── manifest.json
│
├── package.json
├── tsconfig.json
├── tailwind.config.ts
└── next.config.js
Edit src/domain/SRSScheduler.ts:
private readonly MAX_INTERVAL_DAYS = 90 // Change max interval
private readonly AUTO_ARCHIVE_THRESHOLD = 3 // Change auto-archive threshold
private getBaseInterval(difficulty: Difficulty): number {
switch (difficulty) {
case Difficulty.EASY: return 90 // Change intervals
case Difficulty.MEDIUM: return 7
case Difficulty.HARD: return 3
case Difficulty.DIDNT_GET: return 1
}
}Edit src/components/ReviewList.tsx:
const REVIEW_LIMIT = 3 // Change number of visible reviewsEdit tailwind.config.ts to change the color scheme.
- ✅ Chrome/Edge (Desktop & Mobile)
- ✅ Safari (iOS & macOS)
- ✅ Firefox (Desktop & Mobile)
Requires IndexedDB support (all modern browsers).
- Local storage only - All data stored in IndexedDB
- No cloud sync - Works completely offline
- No tracking - Your data never leaves your device
- Clear data: Delete browser data to reset
To add cloud sync in the future, you can integrate Firebase or Supabase with the existing ProblemRepository.
- Check browser console for errors
- Clear browser cache and reload
- Try in incognito mode
- Ensure cookies/storage are enabled
- Check if in Private/Incognito mode (IndexedDB disabled)
- Verify browser supports IndexedDB
# Clear cache and reinstall
rm -rf node_modules .next
npm install
npm run devPotential features to add:
- Cloud sync (Firebase/Supabase)
- LeetCode API integration
- Problem difficulty tags
- Review streaks/statistics
- Export/import data
- Dark mode
- Problem notes/solutions
This is a personal project, but feel free to fork and customize for your own use!
MIT License - Use however you want!