Skip to content

Технологический стек

Слой Решение Примечание
БД PostgreSQL 18 Единственное хранилище: данные, очередь задач, блокировки
Секреты Локальный master key (файл) или Vault Transit Pluggable, см. Шифрование
Метрики Prometheus + OpenTelemetry См. Наблюдаемость
Контейнеризация Docker + Docker Compose
Reverse proxy Traefik v3 TLS для панели

Redis отсутствует намеренно: фоновые задачи и блокировки живут в PostgreSQL (River + advisory locks). Меньше stateful-компонентов — проще self-hosted-эксплуатация; при целевом масштабе выигрыша от отдельного брокера нет.

Слой Решение
Язык Go 1.25+
HTTP Fiber v3
Доступ к БД pgx + sqlc
Миграции Goose + go:embed
Фоновые задачи River (очередь в PostgreSQL)
Auth JWT + Argon2id
Валидация go-playground/validator
OpenAPI Генерация из кода (Swaggo)
Телеметрия OpenTelemetry
Конфигурация Koanf

sqlc вместо GORM: схема и запросы описываются SQL-ом, из них генерируется типизированный Go-код. Нет рантайм-магии ORM, каждый запрос виден и объясним (EXPLAIN), поведение при миграциях предсказуемо.

Слой Решение
Язык Go 1.25+
Связь gRPC-стрим к backend (mTLS), см. gRPC API
Xray Дочерний процесс в том же контейнере
Конфигурация Koanf
Слой Решение
Рантайм / пакеты Bun
Фреймворк React 19 + Vite
Роутинг TanStack Router
Серверный стейт TanStack Query
Глобальный стейт Zustand
Формы React Hook Form + Zod
Стили CSS Modules + токены; Tailwind — точечно
API-клиент openapi-react-query + openapi-typescript
Графики Recharts
Иконки Lucide React
i18n Paraglide JS

Стили строятся на трёх уровнях:

  1. Токены — семантические CSS custom properties в духе shadcn/ui (--background, --primary, --muted-foreground, --sidebar-*, --chart-*) в shared/styles.css; тёмная тема — класс .dark, переопределяющий переменные.
  2. CSS Modules — основной механизм: *.module.css рядом с компонентом, классы сразу в camelCase (.cardHeader). Цвета, отступы, радиусы, шрифты — только через var(--token), сырые значения запрещены. Темизация модулей автоматическая: они ссылаются на переменные и о темах не знают.
  3. Tailwind v4 — подключён (@theme inline пробрасывает те же токены в утилиты), но используется как исключение: одиночная утилита там, где класс в модуле ради одного свойства избыточен. Если утилит у элемента больше двух или комбинация повторяется — это класс в module.css или компонент ui-kit. Произвольные значения ([…]) запрещены везде.

Один источник дизайн-решений — токены: и модули, и утилиты ссылаются на одни переменные, палитра меняется только в styles.css.