Files
lms-sb/ROADMAP.md
T
admins 6d93a7b406 Add lesson comments (Stage 6)
- LessonComment CRUD: addComment / deleteComment server actions
- LessonComments client component with form, avatar, delete
- Comments section at bottom of lesson page (enrolled users only)
- Soft-delete support, moderation for curator/admin
- ROADMAP: moved Квизы to end (Stage 11), marked Stage 7 done

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 15:33:47 +05:00

15 KiB
Raw Blame History

ROADMAP — LMS Second Brain

Стек: Next.js 16.2.2 · React 19 · PostgreSQL 16 · Prisma 7 · Better Auth 1.6 · Tailwind v4 · shadcn/ui · TipTap · Kinescope · Resend · Hetzner Object Storage
Принцип: один этап — одна рабочая фича. Не переходим к следующему, пока текущий не работает end-to-end.


Этап 0 — Каркас, auth, роли ЗАВЕРШЁН (07.04.2026)

Задеплоено на: https://school.second-brain.ru

  • Next.js 16.2.2 (App Router, TypeScript, Tailwind v4)
  • Docker Compose: PostgreSQL 16 (прод на Hetzner)
  • Prisma 7: схема User, Session, Account + полная LMS-модель
  • Better Auth: вход по email/password, роли student/curator/admin
  • proxy.ts: защита маршрутов по сессии
  • Дашборды для трёх ролей
  • Страница входа, регистрации, подтверждения email
  • Seed: admin/curator/student (пароль: Password123!)
  • Dockerfile multi-stage + docker-compose.prod.yml
  • Caddy: school.second-brain.ru → порт 3010

Этап 1 — Курсы → Модули → Уроки (CRUD в админке) ЗАВЕРШЁН (07.04.2026)

  • Prisma-схема: Course, Module, Lesson (с порядком, статусом published)
  • Admin: список курсов, создать / редактировать / удалить курс
  • Admin: список модулей внутри курса, drag-and-drop сортировка
  • Admin: список уроков внутри модуля, drag-and-drop сортировка
  • Admin: редактор урока с TipTap (заголовки, списки, цитаты, код, картинки, ссылки)
  • Загрузка картинок в уроке → Hetzner Object Storage (second-brain-lms, Nuremberg)
  • Поле для Kinescope ID в уроке (просто текстовое, без интеграции — это Этап 2)
  • Публикация/скрытие курса и урока (черновик / опубликован)
  • Управление доступом: выдать / забрать доступ к курсу для пользователя
  • Дизайн в стиле Second Brain: Fira Mono, #F5F5F0, Aubade-карточки
  • Admin: таблица пользователей (/admin/users)


Этап 1.5 — Расширенное управление доступом ЗАВЕРШЁН (07.04.2026)

  • Срок доступа: expiresAt в CourseEnrollment, просроченный подсвечивается красным
  • Категории курсов: таблица Category, /admin/categories, привязка к курсу
  • Расширенный энролл: /admin/users/[userId] — выбор нескольких курсов + срок одной операцией
  • История доступа: AccessLog — каждая операция логируется (кто, когда, метод, примечание)

Этап 2 — Интеграция Kinescope, рендер уроков для ученика

Цель: ученик видит урок с видео Kinescope и текстом.

  • Компонент KinescopePlayer — обёртка над @kinescope/react-kinescope-player
  • Рендер урока для ученика: видео (если есть Kinescope ID) + текст + файлы
  • Загрузка PDF/файлов к уроку (Object Storage), список для скачивания
  • Страница курса для ученика: список модулей и уроков, статус прохождения
  • Навигация по урокам: предыдущий / следующий
  • Блокировка доступа к курсу без enrollment (middleware или server component)
  • Страница «Мои курсы» в личном кабинете ученика

Кинескоп-нюанс: пока без DRM (бесплатный план), просто передаём videoId в компонент. Когда появится платный план — добавим signed URLs в отдельной задаче.

Критерий готовности: ученик открывает урок, смотрит видео из Kinescope, читает текст, скачивает PDF.


Этап 3 — Прогресс и линейное открытие уроков

Цель: ученик проходит курс последовательно, прогресс сохраняется.

  • Prisma: таблица LessonProgress (userId, lessonId, completedAt)
  • Кнопка «Урок завершён» — создаёт запись в LessonProgress
  • Логика блокировки: следующий урок открыт только если предыдущий завершён
  • Прогресс-бар по курсу (% завершённых уроков)
  • Прогресс-бар по модулю
  • API: POST /api/progress/complete — принимает lessonId, создаёт прогресс
  • Иконки статуса уроков в боковой панели: ✓ пройден / 🔒 заблокирован / → текущий

Примечание: если в уроке есть тест (Этап 4) или ДЗ (Этап 5) — кнопка «Завершить» появляется только после их прохождения/отправки. Эту логику дорабатываем на соответствующих этапах.

Критерий готовности: прохожу урок 1, нажимаю «Завершён» — открывается урок 2. Урок 3 заблокирован. Прогресс-бар показывает 33%.


Этап 5 — Домашние задания и обратная связь куратора

Цель: ученик сдаёт ДЗ, куратор оставляет комментарий.

  • Prisma: Homework, HomeworkSubmission, HomeworkFeedback
  • Admin: добавить блок ДЗ к уроку (текст задания)
  • Ученик: форма отправки ДЗ (текст + файлы → Object Storage)
  • Ученик: ДЗ засчитывается автоматически при отправке (урок открывается сразу)
  • Куратор: список ДЗ на проверку (все или по курсу), статус «новое / просмотрено»
  • Куратор: просмотр ДЗ, оставить текстовый комментарий
  • История обмена по ДЗ (ученик может ответить на комментарий куратора)
  • Уведомление ученику когда куратор оставил комментарий (заглушка — реальные email на Этапе 7)

Критерий готовности: отправляю ДЗ — урок открывается. Куратор заходит в панель, видит ДЗ, оставляет комментарий. Ученик видит комментарий в карточке урока.


Этап 6 — Обсуждения под уроками ← ТЕКУЩИЙ

Цель: ученики могут общаться под каждым уроком.

  • Prisma: LessonComment (с поддержкой вложенных ответов — опционально)
  • Рендер треда комментариев под уроком
  • Форма отправки комментария (только для enrolled учеников)
  • Модерация: куратор/админ может удалить комментарий
  • Пагинация или infinite scroll для длинных тредов

Критерий готовности: ученик оставляет комментарий, другой ученик его видит, куратор может удалить.


Этап 7 — Email-уведомления ЗАВЕРШЁН (07.04.2026)

Цель: все участники получают нужные письма через Resend.

  • Базовый email-шаблон (HTML, фирменный стиль)
  • Ученик: подтверждение регистрации (уже частично с Этапа 0, финализировать)
  • Ученик: письмо когда куратор оставил комментарий к ДЗ
  • Ученик: письмо когда ответили на его комментарий в уроке
  • Куратор / Админ: новое ДЗ на проверку
  • Куратор / Админ: новый комментарий в обсуждении
  • Админ: зарегистрирован новый ученик
  • Очередь отправки (edge case: Resend временно недоступен → retry)

Критерий готовности: отправляю ДЗ — куратор получает email. Куратор отвечает — ученик получает email.


Этап 8 — Импорт уроков из Markdown (Obsidian)

Цель: могу импортировать урок из .md-файла Obsidian одним действием.

  • API: POST /api/admin/lessons/import-md — принимает .md-файл
  • Парсинг frontmatter (title, order, kinescopeId и кастомные поля) → метаданные урока
  • Конвертация Markdown-тела в TipTap JSON (через remark / rehype)
  • UI в админке: кнопка «Импортировать из .md» на странице урока
  • Обработка картинок в Markdown (локальные пути → Object Storage)

Критерий готовности: беру .md-файл из Obsidian с frontmatter и текстом → импортирую → урок создан с правильными метаданными и контентом.


Этап 9 — Миграция с emdesell

Цель: все пользователи и контент перенесены в новую LMS.

  • Скрипт импорта пользователей из CSV-экспорта emdesell (email, имя, курсы)
  • Создание пользователей без пароля + письмо «установите пароль»
  • Назначение доступов к курсам по данным из CSV
  • Чек-лист ручного переноса контента (уроки, PDF, структура курсов)
  • Скрипт проверки целостности: все enrolled пользователи имеют доступ к нужным курсам
  • QA: проверить 10 случайных аккаунтов после импорта

Критерий готовности: все ученики из emdesell могут войти в новую LMS и продолжить обучение.


Этап 10 — Telegram-бот и аналитика

Цель: получаю уведомления в Telegram, вижу базовую аналитику.

  • Telegram-бот: уведомление куратору/админу о новом ДЗ
  • Telegram-бот: уведомление об ошибках (500-е, failed email и т.д.)
  • Yandex.Metrika: базовое подключение (pageviews)
  • Admin: простая страница аналитики (активные ученики, прогресс по курсам)

Этап 11 — Деплой на Hetzner

Цель: LMS работает на production-сервере по своему домену с SSL.

  • docker-compose.prod.yml: app + PostgreSQL + Redis + Nginx
  • Nginx: SSL через Let's Encrypt (certbot), reverse proxy на Next.js
  • GitHub Actions: CI/CD pipeline (lint → build → push Docker image → deploy)
  • Резервное копирование PostgreSQL (cron → Object Storage)
  • Мониторинг uptime (UptimeRobot или аналог)
  • .env на сервере через Hetzner Secrets Manager или vault-файл вне репозитория
  • Smoke-тест: регистрация → урок → ДЗ → куратор → email

Критерий MVP готов: создаю курс из админки, добавляю уроки с Kinescope, импортирую ученика из emdesell, даю доступ — ученик регистрируется, проходит урок, сдаёт тест, отправляет ДЗ, получает автодоступ к следующему уроку, позже — комментарий куратора на email.


Этап 11 — Тесты и квизы

Цель: можно добавить тест к уроку, ученик проходит и получает результат.

  • Prisma: Quiz, QuizQuestion, QuizOption, QuizAttempt (схема уже есть)
  • Admin: создание теста к уроку (добавить вопрос → варианты ответов → отметить правильный)
  • Типы вопросов: одиночный выбор, множественный выбор, короткий текст
  • Рендер теста в уроке для ученика
  • Авто-проверка (single/multiple choice), результат сразу
  • Настройка: показывать правильные ответы после прохождения (да/нет)
  • Интеграция с прогрессом: урок с тестом засчитан только после прохождения теста

Критерий готовности: добавляю тест из 3 вопросов к уроку, ученик проходит, видит результат, урок засчитывается.


Бэклог (после MVP)

  • Сертификаты по окончании курса
  • Геймификация (баллы, бейджи, рейтинги)
  • Промокоды и интеграция с платёжными системами
  • Дедлайны и расписания
  • Kinescope DRM (signed URLs) — при переходе на платный план
  • Водяные знаки на PDF и картинках
  • Мобильное приложение