DaydreamMods
Архитектура
Из каких процессов состоит прод и кто за что отвечает.
Репозиторий — один Bun workspace. Два долгоживущих процесса и общие пакеты.
Сайт
apps/web — Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS 3.
Слушает порт 3000. Отдаёт публичные страницы, кабинет, админку и tRPC по адресу /api/trpc. Загрузка картинок и архивов сборки идёт на /api/admin/upload.
Сессия на клиенте лежит в localStorage под ключом ddm_session. Каждый запрос tRPC, если токен есть, шлёт заголовок Authorization: Bearer ….
API
apps/server — Express на Bun, порт 4000.
Две публичные задачи, которые нельзя оставить только во фронтенде:
POST /payments/robokassa/result— серверное подтверждение оплаты;GET /downloads/:token— выдача файла по одноразовому токену.
Остальная бизнес-логика (регистрация, кабинет, админка, создание счёта) живёт в tRPC и вызывается сайтом.
Пакеты
packages/database— Drizzle-схема, миграции, сид. Пароли хеширует Argon2.packages/trpc— процедуры API и запасной каталог контента.packages/payments— сборка ссылки Robokassa и проверка подписи ResultURL.packages/mail— шаблоны писем и отправка SMTP.packages/env— разбор переменных для процесса API.
Как запрос доходит до кода
Nginx принимает 80/443.
/, страницы,/api/trpc,/api/admin/upload— процесс на порту 3000./downloads/и/payments/— процесс на порту 4000.
Загрузка архива вынесена в отдельный location: тело до 1 ГБ, таймауты до часа, буферизация прокси выключена. Иначе большой ZIP обрывается примерно на минуте.
Где лежат файлы
- Код и
.env:/opt/daydreammods. - ZIP сборок:
/opt/daydreammods/storage/packs(переменнаяPACK_STORAGE_DIR). Это неpublic. - Картинки из админки (баннеры, favicon):
apps/web/public/uploads. У них есть URL вида/uploads/…, потому что это оформление, а не платный архив. - База: PostgreSQL на том же сервере, строка в
DATABASE_URL.
Роли процессов systemd
daydreammods-web—next startизapps/web.daydreammods-api—bun src/main.tsизapps/server.
Оба должны читать один и тот же .env. Если мигрировать базу без этого файла, скрипт уйдёт в локальный PGlite и упадёт.