15 KiB
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%.
Этап 4 — Тесты и квизы
Цель: можно добавить тест к уроку, ученик проходит и получает результат.
- Prisma: Quiz, QuizQuestion, QuizOption, QuizAttempt
- Admin: создание теста к уроку (добавить вопрос → варианты ответов → отметить правильный)
- Типы вопросов: одиночный выбор, множественный выбор, короткий текст
- Рендер теста в уроке для ученика
- Авто-проверка (single/multiple choice), результат сразу
- Настройка: показывать правильные ответы после прохождения (да/нет)
- Интеграция с прогрессом: урок с тестом засчитан только после прохождения теста
Критерий готовности: добавляю тест из 3 вопросов к уроку, ученик проходит, видит результат, урок засчитывается.
Этап 5 — Домашние задания и обратная связь куратора
Цель: ученик сдаёт ДЗ, куратор оставляет комментарий.
- Prisma: Homework, HomeworkSubmission, HomeworkFeedback
- Admin: добавить блок ДЗ к уроку (текст задания)
- Ученик: форма отправки ДЗ (текст + файлы → Object Storage)
- Ученик: ДЗ засчитывается автоматически при отправке (урок открывается сразу)
- Куратор: список ДЗ на проверку (все или по курсу), статус «новое / просмотрено»
- Куратор: просмотр ДЗ, оставить текстовый комментарий
- История обмена по ДЗ (ученик может ответить на комментарий куратора)
- Уведомление ученику когда куратор оставил комментарий (заглушка — реальные email на Этапе 7)
Критерий готовности: отправляю ДЗ — урок открывается. Куратор заходит в панель, видит ДЗ, оставляет комментарий. Ученик видит комментарий в карточке урока.
Этап 6 — Обсуждения под уроками
Цель: ученики могут общаться под каждым уроком.
- Prisma: LessonComment (с поддержкой вложенных ответов — опционально)
- Рендер треда комментариев под уроком
- Форма отправки комментария (только для enrolled учеников)
- Модерация: куратор/админ может удалить комментарий
- Пагинация или infinite scroll для длинных тредов
Критерий готовности: ученик оставляет комментарий, другой ученик его видит, куратор может удалить.
Этап 7 — Email-уведомления
Цель: все участники получают нужные письма через Resend.
- Базовый email-шаблон (HTML, фирменный стиль)
- Ученик: подтверждение регистрации (уже частично с Этапа 0, финализировать)
- Ученик: письмо когда куратор оставил комментарий к ДЗ
- Ученик: письмо когда ответили на его комментарий в уроке
- Куратор / Админ: новое ДЗ на проверку
- Куратор / Админ: новый комментарий в обсуждении
- Админ: зарегистрирован новый ученик
- Очередь отправки (edge case: Resend временно недоступен → retry)
Критерий готовности: отправляю ДЗ — куратор получает email. Куратор отвечает — ученик получает email.
Этап 8 — Импорт уроков из Markdown
Цель: могу импортировать урок из .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.
Бэклог (после MVP)
- Сертификаты по окончании курса
- Геймификация (баллы, бейджи, рейтинги)
- Промокоды и интеграция с платёжными системами
- Дедлайны и расписания
- Kinescope DRM (signed URLs) — при переходе на платный план
- Водяные знаки на PDF и картинках
- Мобильное приложение