Перейти к содержанию

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

Принятый стек продукта. Финальная валидация — с нанятым разработчиком; допустимое отклонение описано в разделе «Альтернативы».

Требования, которые определили выбор

  1. Три платформы одним небольшим коллективом: iOS + Android (тренер и клиент) + веб (конструктор тренера — в составе MVP, плюс админка).
  2. Local-first оффлайн с синхронизацией (NFR-3, CLI-3…CLI-5) — закладывается с первого дня, «прикрутить потом» нельзя.
  3. Drag-and-drop конструктор (CON-8), фоновый таймер с заблокированным экраном (TMR-3), загрузка/стриминг видео (VID, этап 2), пуш-уведомления (NTF), графики (PRO-6), HealthKit (INT-1, этап 3).
  4. РФ-специфика: хранение персональных данных в РФ (152-ФЗ), СМС-авторизация, платёжные провайдеры РФ.

Итоговый стек

Клиентская часть

Слой Технология Обоснование
Мобильные приложения (тренер + клиент) React Native + Expo (dev builds), TypeScript Один язык со всем остальным стеком; зрелые библиотеки под все наши фичи; HealthKit/фоновые сервисы доступны через dev builds
Веб (конструктор тренера, админка) React + Vite, TypeScript Веб-конструктор — ядро продукта; React делит с mobile типы, бизнес-логику, парсер и API-клиент
Публичная страница тренера (BRD-2, этап 3) Отдельный небольшой Next.js-сайт Нужен SEO; не тащить SSR в основное SPA ради одной фичи
Монорепо pnpm workspaces + Turborepo Общие пакеты: domain-types, workout-parser, api-client, design-tokens

Оффлайн и синхронизация — ключевое решение

PowerSync (self-hosted) + SQLite на клиенте + PostgreSQL на сервере.

  • На устройстве — полноценная SQLite (op-sqlite в RN, wa-sqlite в браузере): приложение всегда читает и пишет локально, мгновенный UI и честный оффлайн (CLI-3, CLI-4).
  • PowerSync Service реплицирует нужные данные из Postgres в клиентскую SQLite по декларативным sync-правилам (bucket'ы: клиент видит свои программы, тренер — своих клиентов).
  • Записи идут через upload queue в наш backend API — критично для бизнес-правил: сервер, а не клиент, решает вопросы доступа (блокировка при неоплате PAY-1/PAY-5), валидации и прав. Ретраи и очередь оффлайн-записей SDK берёт на себя (CLI-5).
  • Self-hosted редакция закрывает требование 152-ФЗ — весь контур в РФ.
  • Медиа (GIF, видео) через PowerSync не синхронизируется — только структурированные данные; загрузкой медиа управляет отдельный кэш-слой по правилам из 07 — Оффлайн-режим.

Почему PowerSync, а не альтернативы:

Вариант Вердикт
PowerSync ✅ Самый зрелый вариант для production-mobile; полноценные SDK для RN и веба; self-hosted; Postgres
ElectricSQL Хорош для веба, но это read-path-движок общего назначения; RN — не основной фокус
WatermelonDB Только локальная БД, серверный sync-протокол пишем сами — лишний объём работы
CRDT (Automerge/Yjs) Для совместного редактирования документов; наша модель данных реляционная, конфликтов мало — overkill
Самописный sync Классическая яма на месяцы; берём готовое

Серверная часть

Слой Технология Обоснование
API Node.js + TypeScript, NestJS (или Fastify) Один язык с клиентами; структура NestJS удобна при росте команды
Контракт API tRPC внутри монорепо (или REST + OpenAPI — по вкусу команды, некритично) End-to-end типы против целого класса багов
БД PostgreSQL 16+ Источник истины; требование PowerSync
Очереди Redis + BullMQ Уведомления (NTF-1), еженедельные анкеты (SUR-1), транскодинг видео
Файлы и видео S3-совместимое хранилище РФ (Яндекс Object Storage / Selectel) + ffmpeg-воркеры + HLS VID-1 (этап 2); стоимость хранения закладывается в тарифы
Auth Телефонный OTP: СМС-провайдер РФ (SMS Aero / SMSC), дешёвые альтернативы — flash call, Telegram Gateway; JWT + refresh REG-2; Firebase Auth в РФ не опора
Push FCM + APNs через Expo Notifications NTF
Платежи (этап 2) Т-Банк (интернет-эквайринг / касса) Уже используется в других продуктах основателя
Хостинг Яндекс Cloud / Selectel (managed Postgres + Docker Compose на старте) 152-ФЗ; Kubernetes на старте не нужен
Мониторинг Sentry (crash + errors), простые метрики Скорость конструктора — продуктовая метрика (NFR-4), меряем с первого дня

Библиотеки под ключевые фичи

Фича Web Mobile
Drag-and-drop (CON-8) dnd-kit react-native-gesture-handler + reanimated
Графики (PRO-6) recharts victory-native (Skia)
Таймер (TMR-1…4) expo-audio background mode + local notifications; Android — foreground service
Парсер «EMOM 12» (TMR-1, CON-5) Общий TS-пакет workout-parser, правила/грамматика (без LLM в MVP) тот же пакет

Почему не Flutter и не нативная разработка

  • Flutter: веб-конструктор — ядро продукта, а Flutter Web (canvas-рендеринг) слаб для текстонагруженных рабочих SPA: инпуты, буфер обмена, доступность, вес бандла. Пришлось бы писать веб отдельно на React → два стека и два набора компетенций.
  • Нативная разработка / Kotlin Multiplatform: три UI-кодовые базы (SwiftUI, Compose, веб) — не по бюджету маленькой команды на скорости, которая нам нужна.

Обязательные спайки перед стартом (первая неделя разработки)

  1. PowerSync end-to-end: RN + веб-клиент, sync-правила «тренер видит своих клиентов», оффлайн-запись результата → синхронизация. Главный технический риск проекта.
  2. Drag-and-drop длинной тренировки в RN: 60fps на списке из 30+ упражнений.
  3. Парсер тренировочной нотации: «EMOM 12», «10 rounds / 30 sec work / 15 sec rest» — прототип грамматики.

Спайк таймера (звук и вибрация при заблокированном экране — TMR-2, TMR-3) проводится перед началом этапа 2.

Альтернативы

Если нанятый разработчик — сильный Flutter-специалист: мобильные на Flutter допустимы (PowerSync имеет зрелый Flutter SDK), но веб-конструктор всё равно пишется на React — это два стека, и решение надо принимать осознанно. Остальная серверная часть не меняется.

Источники