Architecture
Design principles and data flow of the LoopKit flashcard engine
Design Principles
LoopKit is built around five core principles:
Pluggable Storage
All database operations go through the abstract LoopKitStorage class. This means you can use any database by implementing the storage interface. A Prisma adapter is included out of the box.
Swappable SRS Algorithms
The SM-2 algorithm is the default, but you can implement the SRSAlgorithm interface to use any spaced repetition algorithm (FSRS, Leitner, custom).
Headless-First Frontend
Every React hook exposes the full state and actions. Pre-styled components are optional wrappers around these hooks — use them for rapid prototyping or build your own UI.
API-Driven Integration
The backend exposes services that your API controllers consume. The frontend communicates exclusively through HTTP — there are no direct database calls from the client.
Zero Monolithic Dependencies
The storage interface uses structural typing. The backend package never imports Prisma directly — the adapter handles all ORM-specific logic.
Data Model
NoteType (template definition)
├── FieldDef[] (field schema)
└── TemplateDef[] (front/back templates)
Note (study material)
├── Field[] (field values)
└── tags: string[]
Card (generated from Note + Template)
├── SRS state (ease, interval, due date)
└── belongs to a Deck
Deck (collection of cards)
├── parent/child hierarchy
├── preset or config overrides
└── DeckCounts (new, learning, review, relearning)
ReviewLog (immutable review history)
├── previous card state snapshot
└── new card state snapshotData Flow
Card Creation
- Define a
NoteTypewith fields and templates - Create a
Notewith field values CardGeneratorproduces oneCardper template- Cards start in
newstate with initial SRS parameters
Review Session
ReviewSessionService.buildQueue()collects due cards- Queue ordering: learning/relearning first, then review (most overdue), then new
- Daily limits enforced:
newCardsPerDayandmaxReviewsPerDay - User grades each card:
again,hard,good, oreasy - SM-2 algorithm calculates next state (interval, ease factor, due date)
ReviewLogcreated for each grade action (immutable audit trail)
Card State Machine
┌─── again ───┐
▼ │
new → learning ──good──→ review ◄──good── relearning
│ │ ▲
└── easy ──────────│ │
└─── again ─────────┘- new: Never studied. Enters learning on first review.
- learning: Working through learning steps (e.g., 1min, 10min). Graduates to review on
goodafter all steps. - review: Mature card. Interval grows with each successful review.
- relearning: Lapsed card (answered
againduring review). Works through relearning steps before returning to review.
Configuration Inheritance
DEFAULT_DECK_CONFIG (hardcoded defaults)
└── DeckPreset (named configuration template)
└── Deck.configOverrides (per-deck overrides)DeckService.getEffectiveConfig() merges these layers to produce the final configuration for a deck.