Files
course-craft-service/IMPLEMENTATION.md
2026-02-06 14:53:52 +00:00

13 KiB
Raw Permalink Blame History

Реализация проекта CourseCraft

Документ описывает техническую реализацию платформы CourseCraft — создания образовательных курсов с помощью ИИ.


1. Обзор

CourseCraft — монорепозиторий с тремя приложениями:

Приложение Назначение
web Фронтенд на Next.js 14 (App Router): лендинг, авторизация, дашборд, каталог, прохождение курсов, сертификаты.
api Backend на NestJS: REST API, авторизация (Supabase + JWT), курсы, генерация, записи, прогресс, сертификаты, поиск.
ai-service Воркер на BullMQ: очередь задач генерации курсов, вызовы OpenRouter (структура курса, контент уроков).

Дополнительно: PostgreSQL (Prisma), Redis, Meilisearch. Запуск через Docker Compose из корня проекта.


2. Стек и технологии

  • Frontend: Next.js 14, TypeScript, Tailwind CSS, shadcn/ui, TipTap (редактор/просмотр контента), Supabase Client (auth).
  • Backend: NestJS, Prisma, JWT (обмен Supabase access token на бэкенд-токен), BullMQ, Stripe (платежи).
  • AI: OpenRouter API (GPT-4, Claude и др.), структурированный вывод (JSON), промпты для уточняющих вопросов, outline и контент уроков.
  • Инфраструктура: Docker Compose, pgvector, Meilisearch (поиск курсов).

3. База данных (Prisma)

Схема в packages/database/prisma/schema.prisma.

Основные сущности

  • User — пользователь (supabaseId, email, name, subscriptionTier, role). Связь с UserSettings (customAiModel, theme, language).
  • Subscription — подписка (FREE/PREMIUM/PRO), Stripe, лимиты (coursesCreatedThisMonth).
  • Course — курс (authorId, title, description, slug, status, tags, difficulty, estimatedHours). Связи: Chapter → Lesson.
  • Chapter — глава (courseId, title, description, order).
  • Lesson — урок (chapterId, title, content в TipTap JSON, order, durationMinutes). Опционально: Quiz (questions JSON).
  • CourseGeneration — процесс генерации (userId, initialPrompt, aiModel, status, progress, questions, answers, generatedOutline, courseId, jobId).
  • Enrollment — запись на курс (userId, courseId, progress, completedAt, certificateUrl).
  • LessonProgress — прогресс по уроку (userId, enrollmentId, lessonId, completedAt, quizScore).
  • Review — отзыв по курсу (userId, courseId, rating, content).
  • Certificates — не отдельная таблица: данные для сертификата берутся из Enrollment + User + Course; certificateUrl сохраняется в Enrollment.

Дополнительно: Category, Purchase, CourseGroup, GroupMember, GroupMessage, Homework, HomeworkSubmission, SupportTicket, TicketMessage.


4. Backend (API, NestJS)

Авторизация

  • Supabase Auth — вход/регистрация на фронте.
  • Обмен токена: POST /api/auth/exchange принимает Supabase access token, создаёт/обновляет пользователя в БД, возвращает JWT бэкенда.
  • Защищённые маршруты используют JWT Guard; текущий пользователь — @CurrentUser() user: User.

Основные модули и маршруты

Модуль Назначение
auth exchange token, привязка к Supabase.
users профиль, настройки (в т.ч. customAiModel).
courses CRUD курсов, глав (chapters), уроков (lessons); отдача курса с главами и уроками.
generation Старт генерации (очередь BullMQ), ответы на уточняющие вопросы, продолжение генерации, статус/прогресс.
catalog Публичный каталог курсов (опубликованные), фильтры.
enrollment Запись на курс, прогресс (прохождение уроков, квизы), отзывы, рейтинги, список записей пользователя.
certificates GET /certificates/:courseId — генерация/возврат сертификата (certificateUrl, html); GET /certificates/:courseId/data — данные для страницы сертификата (userName, courseTitle, completedAt).
search Полнотекстовый поиск (Meilisearch).
payments Stripe: подписки, вебхуки.

Сертификаты

  • Доступ только при завершённом курсе (enrollment.completedAt).
  • getCertificateData(userId, courseId) — возвращает { userName, courseTitle, completedAt } для отображения на странице.
  • generateCertificate — формирует HTML сертификата, при необходимости сохраняет certificateUrl в Enrollment, возвращает certificateUrl и html (для обратной совместимости).

5. AI Service (BullMQ + OpenRouter)

Очередь

  • Очередь course-generation (Redis). API добавляет задачи, воркер в ai-service их обрабатывает.
  • Типы задач: generate-course (старт), continue-generation (после ответов на вопросы).

Пайплайн генерации курса

  1. generate-course: анализ запроса → генерация уточняющих вопросов (OpenRouter) → сохранение вопросов в CourseGeneration → статус WAITING_FOR_ANSWERS (ожидание ответов).
  2. Пользователь отвечает через API → ставится задача continue-generation с stage after-questions.
  3. continue-generation: исследование (симуляция) → генерация outline (название, описание, главы, уроки, estimatedTotalHours, difficulty, tags) → создание курса в БД (Course + Chapter + Lesson без контента) → для каждого урока вызов generateLessonContent → запись TipTap JSON в Lesson → обновление подписки (coursesCreatedThisMonth) → статус COMPLETED.

OpenRouter (промпты)

  • generateClarifyingQuestions — уточняющие вопросы, в т.ч. объём курса (короткий / средний / длинный).
  • generateCourseOutline — структура курса по ответам (количество глав и уроков, estimatedMinutes, estimatedTotalHours). При не указанном объёме — средний/длинный (57 глав, 46 уроков в главе, не менее 25 уроков).
  • generateLessonContent — контент урока в формате TipTap JSON (heading, paragraph, bulletList, orderedList, blockquote, codeBlock, mermaid). Промпт требует полный, подробный материал (10001500+ слов), примеры и пояснения, минимум 12 примера/кода на урок.

6. Frontend (Next.js)

Маршруты

  • / — лендинг.
  • /(auth)/login, register, forgot-password — авторизация Supabase.
  • /(dashboard)/dashboard/ — дашборд (sidebar + header): главная, курсы (список, создание, просмотр/прохождение, редактирование), каталог, карточка курса каталога, мои обучения (learning), поиск, настройки, биллинг.
  • /(certificate)/certificate/[courseId] — страница сертификата (без сайдбара): загрузка данных через getCertificateData(courseId), отображение ФИО, названия курса, даты; кнопка «Печать», стили для печати (только блок сертификата).

Авторизация на фронте

  • AuthProvider: Supabase session → при наличии сессии вызов /api/auth/exchange с retry → сохранение JWT в sessionStorage и в памяти; в контексте доступны user, backendUser (id, email, name, subscriptionTier).
  • Все запросы к API через общий клиент с заголовком Authorization: Bearer <token>.

API-клиент (lib/api.ts)

  • Базовый URL API через прокси Next.js или INTERNAL_API_URL на сервере.
  • Методы: auth (exchange), users, courses, chapters, lessons, generation (start, answerQuestions, continue, status), catalog, enrollment (запись, прогресс, отзывы, мои записи), certificates (getCertificate, getCertificateData), search и др.

Ключевые сценарии

  • Создание курса: форма с промптом → старт генерации → опрос уточняющих вопросов → ответы → продолжение генерации → опрос статуса/прогресса до завершения → переход к курсу.
  • Просмотр/прохождение курса: выбор урока, отображение контента (LessonContentViewer по TipTap JSON), отметка урока выполненным, квиз по уроку (LessonQuiz), обновление прогресса, при 100% — возможность открыть сертификат.
  • Сертификат: кнопки «Получить сертификат» (страница курса, мои обучения) открывают в новой вкладке /certificate/[courseId]; страница запрашивает данные и рендерит сертификат с кнопкой «Печать».

7. Инфраструктура и запуск

Docker Compose (из корня)

  • postgres — порт 5432, pgvector.
  • redis — порт 6395 (внешний).
  • meilisearch — порт 7700.
  • api — порт 3125, зависит от postgres, redis, meilisearch; переменные: DATABASE_URL, REDIS_URL, JWT_SECRET, Supabase, NEXT_PUBLIC_APP_URL и т.д.
  • ai-service — зависит от postgres, redis; OPENROUTER_API_KEY, DATABASE_URL, REDIS_URL.
  • web — порт 3080, INTERNAL_API_URL=http://api:3125, Next.js production build.

Запуск:

docker compose --env-file .env up -d

Перезапуск после изменений (например, промпты или API):

docker compose --env-file .env restart ai-service api web

Переменные окружения (.env)

  • База и очереди: DATABASE_URL, REDIS_URL.
  • Auth: NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, JWT_SECRET.
  • AI: OPENROUTER_API_KEY (обязателен для ai-service).
  • Приложение: NEXT_PUBLIC_APP_URL (для ссылок и CORS).
  • Платежи: STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET (при использовании Stripe).
  • Поиск: MEILISEARCH_API_KEY (в docker-compose для meilisearch).

8. Итог

Реализация покрывает: авторизацию через Supabase и JWT, создание курсов по промпту с уточняющими вопросами и генерацией структуры и контента через OpenRouter, каталог и запись на курсы, прохождение с прогрессом и квизами, выдачу сертификата с отдельной страницей для просмотра и печати, тарифы и настраиваемую AI-модель. Документация по быстрому старту и командам — в README.md.