Архитектура и границы приложений
Оглавление · Далее: сайт
Для чего нужен каждый компонент
| Компонент | Задача | Граница |
|---|---|---|
| Next.js | Server Components, страницы, tRPC, webhook, media proxy | Только опубликованный контент через CMS API |
| Mantine | Компоненты, тема и Styles API | Данные приходят через props |
| contracts/Zod | Типы и проверка HTTP данных | TypeScript не заменяет runtime validation |
| Strapi | Редактирование, Draft & Publish, REST и upload provider | Собственные npm/React 18/TS 5 |
| Garage | S3 API и public website bucket | Один узел, без AWS ACL и без HA |
| PostgreSQL | База Strapi | Общий физический процесс |
| Caddy | TLS, reverse proxy | Не заменяет права CMS/API token |
Картина на одном VPS
Исходник схемы
flowchart LR Visitor[Посетитель] --> Caddy Caddy --> Web[Next.js] Caddy --> CMS[Strapi] Caddy -->|media origin| S3[Garage] Web -->|read-only / tagged cache| CMS Web -->|media proxy| S3 CMS -->|S3 upload| S3 CMS --> CMSDB[(strapi)] CMS -->|webhook| Web
База Strapi находится в PostgreSQL; все контейнеры — на одном VPS. Сбой базы, CMS или хоста отражается на обновлении контента. Готовые страницы кеширует Next.js. Read-only token не передаётся браузеру; панель защищена собственным входом Strapi, а публичные изображения читаются без пароля. Draft media-файлы не становятся приватными автоматически.
Структура монорепозитория
apps/
web/ Next.js, Mantine, CMS adapter и серверные тесты
packages/
contracts/ Zod-схемы и типы
infra/
strapi/ Самостоятельный npm-проект CMS
postgres/ Первичное создание пользователей и баз
Caddyfile* Локальный и production reverse proxy
scripts/
setup-env.mjs Локальные секреты
deploy/ Подготовка хоста и применение релизов
.github/workflows/ CI и деплой
docs/ Это руководство
В pnpm workspace входят только apps/* и packages/*. infra/strapi использует
свой package-lock.json, React 18 и TypeScript 5. Изоляция позволяет использовать
современные версии в сайте, не заставляя Strapi разделять несовместимые зависимости.
Зависимости пакетов
Исходник схемы
flowchart TD Contracts[contracts: Zod] --> Web[web: Next.js + tRPC + Mantine] Strapi[Strapi: отдельный npm lockfile]
Стрелки обозначают направление использования: web импортирует contracts.
workspace:* означает локальный пакет, а не скачивание одноимённого пакета из npm.
pnpm -r build учитывает зависимости workspace: сначала собирается contracts.
Turborepo здесь не установлен; команды выполняет pnpm.
Два пути данных
Чтение: Strapi REST → серверный CMS client → Zod/contracts → repository → Server Component или tRPC → посетитель. Все страницы используют одну модель данных. Полная pagination читается до конца; ошибка второй страницы не выдаётся за полный список.
Обновление: Strapi webhook → HTTP handler → Zod → инвалидирование кеша Next.js. Страницы обновляются при следующем посещении без полной пересборки.
Импорт: явный снимок публичного источника → нормализация HTML/дат → upload → Document Service create/publish. Архив нужен для аудита, не для runtime fallback.
Сборка, запуск и проверка типов
- Сборка превращает TypeScript contracts в JavaScript, а Next.js — в production-приложение со статически сгенерированными страницами и ISR.
- Запуск исполняет уже подготовленный код. В dev Next.js обрабатывает исходники.
- Проверка типов ищет ошибки без выполнения бизнес-операций.
- Runtime-валидация проверяет данные, поступившие от внешнего источника.
TypeScript не защищает автоматически от неверного HTTP JSON: сетевой клиент может не использовать TypeScript вообще. Поэтому webhook проверяется Zod в web.
Принятые решения
Next.js выбран для страниц и серверного API. Vike в репозитории не используется.
Mantine выбран для интерфейса. Jest работает через next/jest, поэтому отдельный
Vite-проект для тестирования не нужен. Vitest и Playwright не установлены.
Strapi собирается из стандартного проекта своим Dockerfile. Мы не полагаемся на неопределённый сторонний «готовый Strapi image».
Где смотреть код
Workspace, root scripts, Dockerfile, Compose, контракты.
Наблюдаемость
Новый самостоятельный Compose-стек описан в infra/observability:
браузер → Umami, ошибки Next.js → GlitchTip, Node/Blackbox Exporter → Prometheus →
Grafana. UIKit не импортирует SDK аналитики или ошибок; интеграция находится
в apps/web. Базы аналитики и ошибок отделены от Strapi ролями и владельцами.
Внешняя доставка алертов отключена; Telegram является учебным упражнением. Все системы наблюдения размещаются на том же VPS и разделяют его отказ. Пояснение DevOps · Практическая глава.