Ett eget studieverktyg som jag bygger för att repetera och plugga inför kursprov i mina fristående kurser –
och samtidigt för att fördjupa mig i modern, spec-driven utveckling med Claude Code och OpenSpec.
Appen låter användare skapa kurser och kortlekar, plugga med spaced repetition och generera kort automatiskt
från text eller PDF. Den körs lokalt än så länge; molndrift är nästa steg.
Teknisk översikt
Backend: Java 21, Spring Boot 3.4, Spring Security, Spring Data JPA, Flyway, PostgreSQL 16
Autentisering: JWT i HttpOnly-cookies + CSRF-header; roller (USER/ADMIN) och planer (FREE/PREMIUM)
AI: pluggbart AiProvider-gränssnitt bakom ett kvot- och kostnadsskydd (AiUsageLog, plan-gating)
Spaced repetition: SM-2-algoritmen med per-användarstatus (easeFactor, intervall, dueAt)
Drift & arbetssätt: Docker Compose lokalt; spec-driven utveckling (OpenSpec) med Claude Code – varje funktion som en planerad, granskad ändring
Arkitektur
Flashcards är en monorepo med en React-frontend och en Spring Boot-backend mot PostgreSQL.
Backend är uppdelad i domänmoduler – autentisering, kurser & kortlekar, flashcards, studieläge,
AI-kortgenerering och PDF-import – och anropar en pluggbar AI-provider bakom ett kvot- och kostnadsskydd.
Diagrammet visar hur delarna hänger ihop: orange är egen kod, lila en extern integration och grått data/klient.
Systemöversikt: frontend, API med domänmoduler, databas och den pluggbara AI-providern.
Nyckelfunktioner
Skapa kurser och kortlekar, publika eller privata, med ägarskydd för redigering.
Skapa och redigera flashcards; publika kurser har riktigt innehåll via seed-data.
Studieläge som ett bräde i rundor: vänd korten i valfri ordning, självbetygsätt på kortet, få en rundsammanräkning och spela om de missade korten.
Spaced repetition (SM-2): due-kö för dagens kort och en progress-dashboard.
AI-genererade kortutkast från inklistrad text – granska och spara i bulk till en kortlek.
PDF-import: extrahera text ur en PDF och generera kort från den.
Skapa kurs/kortlek inline på genereringssidan utan att lämna sidan.
Fem valbara teman (mörkt, ljust, mjuk rosa/grön/brun) som sparas mellan besök.
Bygglogg
Projektet byggs stegvis, en OpenSpec-ändring i taget – varje steg planeras, granskas och arkiveras innan nästa börjar.
Klicka på ett steg för att läsa mer.
Steg 01 – Projektgrund · 2026-06-12
Monorepo-skelett med Docker Compose + PostgreSQL, en körbar Spring Boot-backend och en React/TypeScript-frontend med Vite-dev-proxy och health check. Grunden som alla senare steg bygger på.
Steg 02 – Autentisering · 2026-06-18
JWT i HttpOnly-cookies med CSRF-header, User-entity med roll och plan, full Spring Security-konfiguration samt login- och registreringsvyer.
Steg 03 – Kurser & kortlekar · 2026-06-18
CRUD för kurser och kortlekar med synlighet PUBLIC/PRIVATE (publik läsning, skrivning endast för ägaren), en återanvändbar ägarskapskontroll, paginerade listendpoints och list-/detaljvyer i frontend.
Steg 04 – Flashcard-CRUD · 2026-06-19
Card-entity (fram, bak, valfria anteckningar), nästlad /cards-CRUD med korteditor, och seed-data så att de publika kurserna har riktiga, synliga kortlekar och kort.
Steg 05 – Studieläge · 2026-06-19
Study session-API med slumpad/round-robin-kö, sessionsspårning och ett flip-card-gränssnitt för att plugga igenom en kortlek.
Steg 06 – AI-kvotinfrastruktur · 2026-06-19
Ett pluggbart AiProvider-gränssnitt, en AiUsageLog-tabell och plan-gating med månatliga token-kvoter. Kostnadsskyddet byggdes medvetet före någon AI-funktion för att hålla kostnaderna under kontroll.
Steg 07 – AI-kortgenerering · 2026-06-21
Klistra in text → en skyddad AI-pipeline → den pluggbara AI-providern → kortutkast med fram/bak. Användaren granskar utkasten och sparar dem i bulk till en kortlek. Kräver PREMIUM eller ADMIN.
Steg 08 – Spaced repetition · 2026-06-22
Per-användarstatus per kort (easeFactor, intervall, repetitioner, dueAt) som skapas vid första repetitionen; SM-2-algoritmen från betygen Again/Hard/Good/Easy; en due-kö, en repetitionsendpoint och en progress-dashboard i UI:t.
Steg 09 – PDF-import · 2026-06-22
PDF-uppladdning med textutvinning via Apache PDFBox, begränsad till AI-gränsen och inmatad i det befintliga generera→granska→spara-flödet (texten extraheras och slängs; fillagring sparas till deploy-steget).
Möjlighet att skapa en kurs och/eller kortlek direkt i spar-steget på AI-genereringssidan, så att utkast kan sparas utan att lämna sidan (återanvänder befintliga endpoints).
Steg 11 – Frontend-facelift · 2026-06-26
Ett designsystem i Tailwind v4 med fem lugna, valbara helappstemes (mörkt, ljust, mjuk rosa/grön/brun) med persistens och OS-standard, återanvändbara UI-primitiver och omstylade vyer och navigering.
Frontend förnyar nu en utgången session automatiskt: vid ett 401-svar anropas refresh-token-endpointen en gång och det ursprungliga anropet görs om, så sessioner varar i sju dagar istället för att dö efter 15 minuter. Dessutom lite intern städning – delade API-hjälpfunktioner samlade på ett ställe och login-kontrollen flyttad in i UserService.
Steg 13 – Studieläge som bräde · 2026-07-04
En återanvändbar flip-card-primitiv med en äkta 3D-vändning (ren CSS, inget animationsbibliotek; direkt växling för den som valt reducerad rörelse). Studieläget blev ett bräde som spelas i rundor: upp till sex uppvända frågekort delas ut, du vänder dem i valfri ordning, självbetygsätter varje kort på baksidan, och varje runda avslutas med en sammanräkning. De missade korten kan spelas om i ett eget bräde tills allt sitter. Review-läget behåller sitt enkortsflöde men får samma vändning.
Lärdomar
Det här projektet har lika mycket handlat om arbetssättet som om koden. Jag har byggt det spec-drivet med
OpenSpec och Claude Code: varje funktion börjar som en skriven ändring – förslag, design och uppgifter – som granskas
och arkiveras innan nästa påbörjas. Det har gjort det enkelt att hålla ett tydligt fokus per steg och att i efterhand
se exakt varför något byggdes som det byggdes.
En konkret lärdom var att lägga infrastrukturen före funktionen: kvot- och kostnadsskyddet för AI byggdes innan första
AI-anropet, så att en pluggbar provider kunde bytas ut utan att kostnaderna sprang iväg. Att implementera SM-2 för
spaced repetition och att mata in både inklistrad text och PDF i samma generera→granska→spara-flöde gav också bra
insikter i hur man håller ett växande system sammanhållet snarare än hopplockat.