A study app: spaced-repetition flashcards, practice quizzes, timed exams, a Match game, a focus timer and live multiplayer quizzes. Scan a PDF, Word document or photo of your notes and it builds the study set for you.
Requires Node 20+.
npm install
npm run dev # http://localhost:3000| Command | What it does |
|---|---|
npm run dev |
Dev server with hot reload |
npm run build |
Production build into dist/ (includes the offline service worker) |
npm start |
Serves dist/ in production mode on $PORT (default 3000) |
npm test |
Unit tests (generator, answer checking, import parsing, levels) |
npm run lint |
Type-check |
npm run check |
Type-check, test and build in one go; run before deploying |
Copy .env.example to .env:
VITE_SUPABASE_URL,VITE_SUPABASE_ANON_KEY: the Supabase project used for live games. Only live games touch the network.PORT: port fornpm start.
- Your data stays on the device. Decks, progress, XP, streaks and settings live in
localStorageunderkawe:v1(src/lib/store.ts). Settings has backup download and restore. - Sign-in is temporarily off. Everyone is a local guest.
useAuth()insrc/contexts/AuthContext.tsxis the single seam for bringing real auth back. - Document scanning is on-device (
src/lib/extract.ts,src/lib/generate.ts). pdf.js reads PDFs, mammoth reads.docx, and tesseract.js runs OCR on photos and scanned PDFs. The OCR language data (about 10 MB) is downloaded on the first scan. The generator finds definitions, abbreviations and informative sentences, then writes flashcards and multiple-choice, true/false and fill-in-the-blank questions using the document's own terms as wrong answers. No text leaves the browser. - Live games use the Supabase tables in
supabase_schema.sql. Guest players need row-level-security policies that allow anonymous inserts intoquizzes,sessions,participantsandresponses.
Apple-style tokens in src/index.css, with light and dark themes. Geist sets the interface and Newsreader sets titles; both are self-hosted. Every control state is defined in one place (btn, btn-*, field, hoverable), and all icons come from Iconify through src/components/icons.tsx. Motion uses critically damped springs (src/lib/motion.ts) and respects reduced-motion settings.