Кейс · Веб-приложение · TypeScript
flashcards-sm2: «Карточки», картотека с интервальным повторением SM-2
Концепт-приложение на Vue 3: колоды карточек и повторение по алгоритму SM-2, офлайн и без бэкенда, данные в IndexedDB. Импорт CSV/TSV сам определяет разделитель и кодировку (UTF-8, UTF-16 по BOM, Windows-1251), экспорт защищён от CSV-injection, есть полный JSON-бэкап со строгой валидацией. Статистика на SVG: прогноз на 30 дней, зрелость карточек, ретеншен.
- Vue 3
- TypeScript
- Vite
- IndexedDB
- PWA
- SM-2
- fast-check
- vitest
- axe
- Cloudflare Pages
- GitHub Actions
01 · Как выглядит
Скриншоты


02 · О проекте
Что это и зачем
Задача: офлайн-картотека, где расписание повторений не ломается от смены часового пояса и перехода на летнее время, а импорт чужих CSV не требует угадывать кодировку.
Решение: Vue 3 + TypeScript, алгоритм SM-2 в чистой логике без DOM, данные в IndexedDB. «Сегодня» это календарная дата устройства, расписание хранится датами, а не метками времени.
Ограничения
Концепт: нет синхронизации между устройствами, изображений и звука.
Обратные карточки не создаются автоматически.
Данные привязаны к браузеру и профилю: очистка данных сайта их удалит, поэтому есть JSON-бэкап.
Что внутри
- SM-2 по описанию SuperMemo-2: EF от 1.3, старт 2.5, интервалы 1 и 6 дней, далее max(prev+1, round(prev·EF)), предел 3650 дней; отличия от оригинала описаны в README
- Импорт CSV/TSV: кавычки и переносы в ячейках, разделитель и кодировка (UTF-8, UTF-16 по BOM, Windows-1251) определяются автоматически; лимиты 1 МБ, 5000 строк
- Экспорт CSV с защитой от CSV-injection и полный JSON-бэкап со строгой валидацией при загрузке
- Статистика на SVG: прогноз повторений на 30 дней, зрелость карточек, ретеншен, тепловая карта на 26 недель
- 30 тестов vitest + fast-check; переворот карточки на чистом CSS, клавиатура (пробел, 1–4), axe 0
- Выложено на Cloudflare Pages, PWA работает офлайн
03 · Как запустить
Запуск одной командой
git clone <репозиторий по запросу> flashcards-sm2
cd flashcards-sm2
npm ci
npm run dev04 · Код
Репозиторий приватный
Исходники лежат в приватном репозитории. Напишите в Telegram, открою доступ.
Запросить код