Учебное руководство
Главы руководства
На этой странице

Архитектура и границы приложений

Оглавление · Далее: сайт

Для чего нужен каждый компонент

КомпонентЗадачаГраница
Next.jsServer 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
GarageS3 API и public website bucketОдин узел, без AWS ACL и без HA
PostgreSQLБаза StrapiОбщий физический процесс
CaddyTLS, 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 · Практическая глава.