Мультиарендная SaaS-платформа для учебных центров и школ
Расписание · Посещаемость · Журнал · Домашние задания · Оплаты · Мобильный кабинет
О проекте · Возможности · Архитектура · Быстрый старт · Качество · Безопасность · Документация
e-darschi — облачная LMS, которую учебный центр арендует как сервис: без серверов, без разработчиков
и без ручной настройки. Один экземпляр приложения обслуживает множество центров, при этом данные каждого
центра физически лежат в общей базе, но изолированы на уровне клиента Prisma — запрос без centerId
просто не соберётся.
Платформа закрывает полный цикл работы центра: от заявки и пробного урока до оплат, отчётности и мобильного кабинета родителя.
| 40 моделей данных |
56 экранов |
6 ролей |
133 тестовых файла |
![]() |
![]() |
| Светлая тема — основная для публичной части | Тёмная тема — переключатель в шапке, выбор запоминается |
![]() |
![]() |
![]() |
| Преимущества | Мобильная экосистема | Тарифы |
Мобильная версия: тот же интерфейс, адаптированный под 390 px
| Модуль | Что умеет |
|---|---|
| Центры | Создание, карточка центра, владельцы, блокировка / пауза / отмена подписки с мгновенным отзывом доступа |
| Тарифы и подписки | Планы, лимиты (ученики, филиалы, сотрудники), статусы оплат и продлений |
| Поддержка | Тикеты центров, ответы, доступ PLATFORM_SUPPORT в режиме только чтение |
| Аудит | Неизменяемый журнал критических действий по всей платформе |
| SEO и developer API | Управление метаданными, health-check, аудит и владельцы центров |
| Модуль | Что умеет |
|---|---|
| Студенты и родители | Карточки, статусы (ACTIVE / ARCHIVED), привязка родитель → ребёнок, импорт и экспорт CSV |
| Группы и курсы | Курсы, модули, группы, зачисления, преподаватели, филиалы |
| Расписание | Слоты с защитой от конфликтов преподавателя / аудитории / группы, замены, отмена с причиной, экспорт в iCal |
| Посещаемость | Отметки по занятию, опоздания, автоматическое попадание в зону внимания при посещаемости < 80% |
| Журнал оценок | Оценки A–F, средний балл, GPA, блокировка журнала после закрытия периода |
| Домашние задания | Выдача, сдача, проверка, обратная связь, вложения, тесты с автопроверкой |
| Оплаты | Начисления, оплаты, задолженности, статусы (Payme / Click / Uzum — интеграционные точки) |
| Отчёты | Посещаемость, успеваемость, выручка, загрузка групп и преподавателей |
| Объявления и уведомления | Рассылки центром, e-mail, Telegram / SMS / push-транспорты |
| Сотрудники и инвайты | Приглашения по коду, роли, отзыв сессий, журнал действий |
- Преподаватель — свои группы и расписание, посещаемость, оценки, домашние задания и тесты.
- Студент — расписание, материалы, сдача ДЗ, онлайн-тесты с мгновенным результатом, свои оценки и GPA.
- Родитель — успеваемость, посещаемость и оплаты ребёнка в одном экране.
flowchart TB
B["🌐 Браузер<br/>RU · UZ-Latn"] -->|HTTPS| N["Next.js 14 · App Router<br/>Server Components + Route Handlers"]
N -->|"requireTenantAccess()"| T["tenantCtx.getTenantDb()<br/>Prisma Client, ограниченный centerId"]
T --> P[("PostgreSQL 16<br/>40 моделей · 13 миграций")]
N --> A["AuditLog · UserSession<br/>RateLimitRecord · EmailOutbox"]
A --> P
style B fill:#0B1220,stroke:#1D4ED8,color:#fff
style N fill:#1D4ED8,stroke:#1D4ED8,color:#fff
style T fill:#EEF3FF,stroke:#1D4ED8,color:#0B1220
style P fill:#0B1220,stroke:#5B8CFF,color:#fff
style A fill:#F6F7FB,stroke:#C7D2E2,color:#0B1220
Ключевые решения
- Изоляция арендаторов в коде, а не в договорённостях. Модели с
centerIdдоступны только через обёрткуgetTenantDb(): она подставляетcenterIdв каждый запрос, отклоняет попытки его переопределить и проверяет внешние связи по DMMF. Импорт «сырого» клиента запрещён правилом ESLint. - Fail-closed. Нет сессии — редирект на логин до tenant-проверки; нет доступа — 403; центр на паузе — запись запрещена, чтение остаётся.
- Сессии с отзывом. JWT в httpOnly cookie + запись
UserSessionс хэшемjti: выход, смена пароля и блокировка центра гасят токен на сервере. - Единый UI-язык. Токены
ink / paper / line / brandи scoped-тема.public-shell; админ-панели не зависят от публичной темы.
| Слой | Технологии |
|---|---|
| Frontend | Next.js 14 (App Router), React 18, TypeScript, Tailwind CSS, Framer Motion, Lucide |
| Backend | Route Handlers, Zod, JWT (httpOnly + jti), bcrypt, PostgreSQL rate limiter |
| Данные | PostgreSQL 16, Prisma 5 (40 моделей, 13 миграций) |
| Интеграции | Resend (e-mail), S3 / Cloudflare R2 (presigned uploads), Telegram / SMS-транспорты |
| Качество | Vitest + Testing Library (jsdom), ESLint, tsc --noEmit, coverage v8, GitHub Actions |
| Инфраструктура | Docker, docker-compose (prod), healthcheck, Vercel-совместимая сборка |
- Node.js ≥ 20 (см.
.nvmrc) - npm ≥ 9
- PostgreSQL 16
git clone https://github.com/u2kdev/edu.git
cd edu
npm cicp .env.example .envМинимум для локального запуска:
DATABASE_URL="postgresql://postgres:password@localhost:5432/lms?schema=public"
DIRECT_URL="postgresql://postgres:password@localhost:5432/lms?schema=public"
JWT_SECRET="super-secret-jwt-key-at-least-32-chars-long"
APP_URL="http://localhost:3000"
DEV_LOGIN="true"
DEV_EMAIL_LOG="false"Полный список переменных — e-mail, cron, storage, proxy
| Переменная | Назначение |
|---|---|
EMAIL_PROVIDER |
memory · console · resend |
RESEND_API_KEY, EMAIL_FROM |
Отправка писем через Resend |
CRON_SECRET |
Защита /api/cron/* |
FEATURE_UPLOADS, STORAGE_* |
Включение и настройка S3 / R2 |
TRUSTED_PROXY_HOPS |
Сколько прокси перед приложением (IP для rate limit и аудита) |
NEXT_PUBLIC_APP_URL |
Публичный адрес приложения |
Полный перечень и комментарии — в .env.example.
npm run prisma:generate # Prisma Client
npx prisma migrate deploy # применить миграции
npm run prisma:seed # тарифы, суперадмин, демо-центрnpm run devОткройте http://localhost:3000 — лендинг, http://localhost:3000/login — вход.
Демо-роли и тестовые аккаунты описаны в docs/DEMO.md.
| Команда | Что делает |
|---|---|
npm run dev |
Dev-сервер Next.js |
npm run build / npm start |
Production-сборка и запуск |
npm run verify |
Полный контур: tsc → ESLint → Vitest → build |
npm run lint |
ESLint (src + tests) |
npm test / npm run test:watch |
Тесты один раз / в watch-режиме |
npm run test:coverage |
Тесты с покрытием (порог CI: 66 / 55 / 62 / 66) |
npm run prisma:generate |
Генерация Prisma Client |
npm run prisma:seed |
Начальные данные |
npm run prisma:db-push |
Быстрая синхронизация схемы (dev) |
npm run setup:first-owner |
Создание первого суперадмина |
npm run verify| Проверка | Результат |
|---|---|
tsc --noEmit |
0 ошибок |
| ESLint | 0 ошибок |
| Vitest | 133 файла · 1166 тестов на реальной PostgreSQL |
| Coverage | 79.6 % stmts · 68.8 % branch · 86.5 % funcs · 80.5 % lines |
next build |
✅ успешно |
Тесты работают с отдельной базой (TEST_DATABASE_URL, по умолчанию
postgresql://postgres:admin@localhost:5432/lms_test) и создают данные в транзакциях.
CI — что запускается на каждый push и pull request
.github/workflows/ci.yml, ветки main и feature/lms-upgrade, сервисный PostgreSQL 16:
npm cinpx prisma generatenpx prisma migrate deploynpx tsc --noEmitnpm run lintnpx vitest runnpm run build
- Мультитенантность —
centerIdпринудительно добавляется в каждый запрос; попытка подменить его или сослаться на чужую запись возвращает403. - Аутентификация — httpOnly JWT, серверные сессии с
jti, отзыв при выходе и смене пароля, подтверждение e-mail, блокировка после серии неудачных попыток. - Rate limiting — в PostgreSQL (
RateLimitRecord), работает при нескольких инстансах; fail-closed. - CSRF и CSP — проверка origin для мутаций, строгие заголовки безопасности.
- Приватность оценок — правильные ответы тестов не уходят на клиент до сдачи.
- Аудит —
AuditLogиActivityLogфиксируют критичные действия платформы и центра. - Пароли — bcrypt, политика сложности, сброс по одноразовому токену.
⚠️ Если вы форкнули или склонировали репозиторий:.envиtransmitter/не входят в репозиторий, но история прежних коммитов могла содержать токен Telegram-бота. Перед публичным деплоем сменитеTELEGRAM_BOT_TOKENв @BotFather и все ключи из.env.example.
| Роль | Доступ |
|---|---|
SUPERADMIN / PLATFORM_ADMIN |
Платформа: центры, тарифы, подписки, поддержка, аудит, SEO |
PLATFORM_SUPPORT |
Поддержка платформы, read-only внутри центра |
DIRECTOR |
Центр: сотрудники, студенты, группы, расписание, оплаты, отчёты, тариф |
TEACHER |
Свои группы: расписание, посещаемость, оценки, ДЗ и тесты |
STUDENT |
Расписание, материалы, ДЗ, тесты, оценки, посещаемость |
PARENT |
Успеваемость, посещаемость и оплаты ребёнка |
| Документ | О чём |
|---|---|
docs/ARCHITECTURE.md |
Мультитенантность, getTenantDb, слой данных |
docs/DEMO.md |
Демо-роли и сценарии показа |
docs/DEPLOY.md |
Production-деплой, Docker, переменные |
docs/I18N.md |
Локализация RU / UZ-Latn, ключи и правила |
docs/RECOVERY.md |
Бэкапы и восстановление |
docs/LAUNCH_CHECKLIST.md |
Чек-лист перед запуском |
docs/STATUS.md · docs/ROADMAP.md |
Состояние и планы |
docker compose -f docker-compose.prod.yml up -d --buildDockerfile— multi-stage сборка, non-root пользователь, healthcheck.docker-compose.prod.yml— приложение + PostgreSQL + переменные окружения.vercel.json— альтернативный деплой на Vercel.- Пошагово — в
DEPLOY.mdиdocs/DEPLOY.md.
e-darschi — меньше бумажной работы, больше времени на учеников.
Сделано в Ташкенте · © 2026 e-darschi. Все права защищены.





