Сервисы и порты
Детальный разбор пяти сервисов NG-Metrics — стек, ответственность, локальные порты и точки входа.
Сервисы и порты
Frontend (Next.js)
Директория: frontend/
Стек: Next.js 15 (App Router), TypeScript, Tailwind CSS 4, Supabase Auth, next-intl, Zustand, TanStack Query, SurveyJS.
Менеджер пакетов: Yarn 1.22.
Ответственность. Веб-интерфейс для всех ролей: вход, дашборд бригадира/сотрудника, страница рецензирования отчёта, публичная страница отчёта, страница отписки от уведомлений, страницы аутентификации (sign-in / sign-up / forgot-password / invite / callback).
Маршрутизация. Локали в URL: /{ru|en}/.... Авторизованная зона лежит в группе (auth) — /{locale}/dashboard/reports. Публичные страницы: /{locale}/report/{id}, /{locale}/unsubscribe.
Дашборд. На пути /{locale}/dashboard/reports живёт основной интерфейс рецензирования. Поддерживает desktop- и mobile-варианты (компоненты в dashboard/reports/components/{desktop,mobile}/). Принимает query-параметр ?visit=<id> — для прямых ссылок на конкретный наряд.
API-роуты Next.js. Используются как прокси к бэкенду для SurveyJS lazy loading (/api/survey/materials, /api/survey/services, /api/survey/workers) и для Open Graph картинок (/api/og).
Команды:
yarn dev # dev-сервер (Turbopack + Sentry Spotlight)
yarn build && yarn start
yarn test # Vitest unit-тесты
yarn test:e2e # Playwright
yarn storybook # Storybook на :6006
yarn check:types # tsc --noEmit
yarn lint:fixBackend / Garden (Django)
Директория: garden/
Стек: Django 5.2, Django REST Framework, drf-spectacular (OpenAPI), PostgreSQL 17, simple-history, KSUID, MJML, Resend, Celery 5.4 (Redis broker).
Менеджер пакетов: UV.
Ответственность. Ядро бизнес-логики и единственный владелец схемы БД. Реализует REST API, рендерит email через MJML, отправляет уведомления через Resend и Redis Stream, хранит загруженные файлы в Supabase S3.
В проде сервис разворачивается в два контейнера:
- web (
ng-metrics-backend) — gunicorn, обслуживает HTTP, применяет миграции при старте. - worker (
ng-metrics-backend-worker) —celery -A ng_metrics worker, исполняет фоновые задачи (сейчас — отправка уведомлений). Использует тот же образ; entrypoint очищен, чтобы не запускать миграции повторно.
В dev по умолчанию CELERY_TASK_ALWAYS_EAGER=true — задачи выполняются синхронно, отдельный воркер не нужен.
Модули (garden/modules/):
| Модуль | Что в нём |
|---|---|
account | Модель User, аутентификация Supabase, эндпоинт /api/workers/, signal-обработчики |
client | Client, ClientObject, ContactPerson, ClientInvite — клиенты, объекты, контактные лица, приглашения |
service_visit | ServiceVisit, ServiceVisitMember — наряды и состав бригад; экшены смены статуса |
report | Report, ReportSurveyTemplate, FileAttachment, ReportDelivery — отчёты, шаблоны, вложения, история доставок |
notification | NotificationPreference, NotificationRouter, бэкенды, recipient resolvers, webhook-приёмники |
material | Material, MaterialPrice, ServiceVisitMaterial — материалы и расход на наряде |
service | Service, ServicePrice, ServiceVisitService — услуги и факт выполнения |
communication | ChatwootContact — связь пользователя с записью в Chatwoot |
shared | Базовые классы (BaseModel, KSUID, аутентификация) |
work | Deprecated. Сохранён как unmanaged-модель для исторических FK в старых миграциях. Использовать service_visit. |
Команды:
uv sync
python manage.py migrate
python manage.py runserver # :8000 (dev)
python manage.py seed_report_templates
make lint # ruff + mypy
make test # pytestПорты: 8000 в dev, 7000 в проде (отличие важно).
Telegram-бот
Директория: bot/
Стек: Aiogram 3.20, FastAPI, SQLAlchemy 2.0, Alembic, Redis, MyPy strict.
Менеджер пакетов: UV.
Ответственность. Доставка уведомлений в Telegram, привязка Telegram-аккаунтов к пользователям, поддержка через Chatwoot, кнопка Mini App.
Точки входа:
bot/app/__main__.py— главный entrypoint. Запускает либо webhook-режим, либо polling.bot/app/endpoints/telegram.py— Aiogram-хендлеры (команды бота).bot/app/endpoints/chatwoot.py— приёмник входящих сообщений из Chatwoot.bot/app/endpoints/healthcheck.py—/health.bot/app/runners/{webhook,polling}.py— режимы запуска.bot/app/services/redis/— подписка на Redis Stream от Garden.bot/app/services/postgres/— read-only SQLAlchemy для зеркал моделей Django.
База данных. Бот использует PostgreSQL только в режиме чтения для тех таблиц, что владеет Django. Для собственных «горячих» данных (FSM-состояния Aiogram, сессии Chatwoot) используется Redis (DB2).
Команды:
make app-run-db # стартовать PG + Redis в Docker
make run # запустить бота локально (polling)
make app-build && make app-run # всё в Docker
make lint # mypy + ruffПорт: 8080 (FastAPI для webhook от Telegram + Chatwoot).
Роль ng-metrics-bot в Ansible-плейбуке закомментирована из-за ограничений Telegram в РФ. Код сохранён, локальный запуск работает.
Supabase
Директория: supabase/
Стек: PostgreSQL 17, Supabase Auth, Supabase Storage (S3-совместимый), Deno Edge Functions, Resend.
Менеджер пакетов: Supabase CLI.
Ответственность. Базы данных, аутентификация, S3-хранилище, тонкий webhook-слой для Auth-событий и транзакционных писем.
Edge Functions (supabase/functions/):
| Функция | Триггер | Что делает |
|---|---|---|
send-email | Supabase Auth send-email hook | Шлёт письма приглашения / сброса пароля / смены email через Resend. Шаблоны на React Email (TSX), двуязычные (ru/en по user_metadata.lang). |
auth-sync | Webhook Supabase Auth (USER_CREATED / USER_UPDATED) | Передаёт событие в Django для синхронизации User.supabase_uid. |
set-role | HTTP вызов из фронта | Обновляет app_metadata.role в Supabase Auth (вызывается при изменении роли пользователя). |
Локальные порты:
| Что | Порт |
|---|---|
| Supabase API (Kong) | 54321 |
| PostgreSQL | 54322 |
| Supabase Studio | 54323 |
| Inbucket (тестовый SMTP) | 54324 |
Edge Functions (make serve) | 8000 |
Команды:
make start # PostgreSQL + Auth + Storage + Studio
make serve # локальный запуск Edge Functions
make tunnel # Tuna-туннели для тестирования вебхуков
make migrateИнфраструктура (Ansible)
Директория: ansible/
Стек: Ansible 11.1, Docker, Traefik (единый reverse-proxy с Let's Encrypt), Infisical (секреты).
Менеджер пакетов: Poetry.
Ответственность. Деплой всех сервисов на одном хосте через Docker. Управление секретами через Infisical. HTTPS через Traefik (single reverse-proxy, заменивший связку Caddy + Nginx).
Главный плейбук: playbooks/prod/ng-metrics.yaml. Порядок ролей:
infisical— загрузка секретов.common— базовое окружение, docker, swap.supabase— БД, Auth, Storage, Edge Functions.system— Docker-сети (ng_metrics), Redis, Traefik (reverse-proxy + HTTPS).ng-metrics-backend— Django на порту 7000.ng-metrics-frontend— Next.js на порту 3000.ng-metrics-bot— отключено в текущей версии (закомментировано).chatwoot— отключено в текущей версии.
Redis распределён по базам:
- DB0 — Django (Redis Stream + кэш).
- DB1 — Chatwoot (когда включён).
- DB2 — Telegram-бот (FSM-состояния, сессии).
Локальные порты — единая таблица
| Сервис | Порт | Контекст |
|---|---|---|
| Frontend (Next.js) | 3000 | Прод и dev |
| Backend (Django dev) | 8000 | Только dev |
| Backend (Django prod) | 7000 | Только прод |
| Telegram-бот FastAPI | 8080 | Прод и dev |
| Supabase API (Kong) | 54321 | Локально |
| PostgreSQL | 54322 | Локально |
| Supabase Studio | 54323 | Локально |
| Inbucket | 54324 | Локально (Mailhog-аналог) |
| Edge Functions | 8000 | Локально (make serve) |
| Storybook | 6006 | Только dev |
Порядок запуска локально
# 1. Supabase — без него ничего не работает
cd supabase && make start
# 2. Backend — миграции и API
cd ../garden && python manage.py migrate
python manage.py runserver
# 3. Frontend
cd ../frontend && yarn dev
# 4. Telegram-бот (если нужен)
cd ../bot && make app-run-db && make run
# 5. Туннели (если тестируете webhook'и от Supabase)
cd ../supabase && make tunnelTuna-туннели публикуют сервисы в РФ-регионе:
- Frontend:
web-knotta.ru.tuna.am - Supabase API:
service-knotta.ru.tuna.am - Backend API:
api-knotta.ru.tuna.am - Telegram-бот:
bot-knotta.ru.tuna.am