Обзор
Гардероб — каталог своих вещей и коллажи
Кроссплатформенное приложение (iOS + Android) на React Native / Expo. По сути — каталог собственных вещей в эстетике Farfetch: белый фон, тонкие линии, много воздуха, вещи как товары.
- фотографируете вещь на камеру (или берёте из галереи);
- приложение вырезает фон — вещь попадает в каталог;
- собираете из вещей коллажи на белом листе: перетаскиваете, меняете размер и поворот, двигаете слои;
- при желании включаете режим «Манекен» — вещи автоматически садятся на фигуру по опорным точкам.
Это рабочий прототип ядра: путь «сфотографировал → вещь в каталоге → собрал коллаж» реализован целиком и работает офлайн.
Что уже работает
| Блок | Статус |
|---|---|
| Белый интерфейс в духе Farfetch: каталог, карточка товара, тонкие линии | ✅ |
| Камера с рамкой-гайдом, съёмка вещи | ✅ |
| Импорт из галереи | ✅ |
| Локальное вырезание фона (без сети и без API-ключей) | ✅ |
| Ручная правка: кисть «стереть / оставить», сброс, кроп с зумом и отменой | ✅ |
| Автоопределение цвета и категории (локальная эвристика) | ✅ |
| Каталог: сетка 2 колонки, поиск, фильтры по категориям | ✅ |
| Пакетный импорт: до 20 фото из галереи за раз, общая проверка и сохранение | ✅ |
| Коллаж: свободное размещение, перетаскивание, щипок, поворот, слои | ✅ |
| Фото-блоки: любые картинки из галереи на листе (мудборд) | ✅ |
| Фон листа: белый / тёплый / серый | ✅ |
| Текст на листе: подпись, цвет, размер (шрифт Inter, OFL) | ✅ |
| Правка края сразу после съёмки, в том числе «начать с исходного фото» | ✅ |
| Избранное как фильтр в каталоге | ✅ |
| Превью коллажей в списке (снимок листа при сохранении) | ✅ |
| Экспорт PNG в 3× (высокое разрешение) | ✅ |
| Онбординг из трёх экранов при первом запуске | ✅ |
| Редактор опорных точек вещи с живым превью посадки | ✅ |
| Сетка-направляющие и магнит к центру листа | ✅ |
| Режим «Манекен»: посадка вещи по фигуре через TPS-деформацию | ✅ |
| Профиль: 5 обхватов, тон кожи, волосы, 4 причёски | ✅ |
| Сохранение коллажей, локальная база SQLite, полный офлайн | ✅ |
| Вход через Яндекс ID (OAuth через собственный API на сервере) | ✅ |
| Синхронизация: вещи, коллажи, профиль и картинки между устройствами | ✅ |
| Автосинхронизация: после правок, при старте и возврате в приложение | ✅ |
| Обновление токенов по refresh без повторного входа | ✅ |
| Экспорт коллажа в PNG и системный шаринг | ✅ |
| Юнит-тесты математики посадки и вырезания | ✅ (19 тестов) |
| Облачное вырезание фона и VLM-распознавание | 🔌 интерфейс готов, включается переменной окружения |
| Примерка коллажа на сгенерированных моделей (VTON) | 📋 следующий этап, см. docs/03-ai-pipeline.md |
| Аккаунты и синхронизация между устройствами | 📋 следующий этап, см. docs/02-architecture.md |
Как читать документацию
Откройте **docs.html** двойным щелчком — это вся документация (этот файл и пять разборов из docs/), собранная в одну страницу с навигацией. Работает офлайн, ничего устанавливать не нужно.
Исходники — обычные markdown-файлы в docs/. Их можно править в любом редакторе (удобнее всего VS Code), а docs.html — просто снимок для чтения.
Запуск на телефоне
Самый простой путь — двойной щелчок по **START.bat** в корне проекта: скрипт проверит Node.js, поставит зависимости и запустит Expo.
Вручную:
- Установите Node.js LTS с nodejs.org (обычный установщик, настройки по умолчанию).
- Установите на телефон Expo Go (App Store / Google Play) и обновите его до последней версии.
- Подключите телефон и компьютер к одной Wi-Fi сети.
- В PowerShell:
cd apps/mobile
npm install
npx expo start
- Отсканируйте QR-код из терминала: на Android — прямо в Expo Go, на iPhone — камерой (предложит открыть Expo Go).
Все нативные модули приложения (Skia, камера, SQLite, Reanimated) входят в Expo Go, поэтому отдельная сборка не нужна — приложение запустится сразу.
Если телефон не видит сервер:
- разрешите Node.js в брандмауэре Windows (при первом запуске появится запрос);
- проверьте, что сеть не «гостевая» с изоляцией клиентов;
- запустите через туннель:
npx expo start --tunnel.
Если Expo Go пишет «project is incompatible» — обновите Expo Go до последней версии.
Проверки
npm run typecheck # tsc по всему приложению
npm run test:core # юнит-тесты математики (компилируются в .tmp и гоняются в Node)
Настройки (необязательно)
Создайте apps/mobile/.env:
# Свой сервис вырезания фона: POST multipart -> { image: "<base64 png>", width, height, quality }
EXPO_PUBLIC_CUTOUT_URL=https://your-api.example/cutout
# Свой сервис распознавания: POST { image: "data:image/png;base64,...", category } -> { name, tags }
EXPO_PUBLIC_VISION_URL=https://your-api.example/tags
Без этих переменных приложение полностью работоспособно: вырезание идёт локальным алгоритмом, теги — эвристикой по цвету.
Структура
apps/mobile/
src/
app/ экраны (expo-router): каталог, коллажи, профиль, камера, карточка вещи, редактор
components/ UI-кит, плитка каталога, лист коллажа на Skia, манекен, слайдер
core/ чистая логика без React Native — тестируется в Node
body.ts антропометрия -> силуэт манекена и опорные точки
rig.ts шаблоны опорных точек по категориям одежды
tps.ts thin plate spline — деформация вещи под фигуру
mesh.ts треугольная сетка для Skia
outfit.ts слои, раскладка коллажа, порядок отрисовки
cutout.ts вырезание фона по цвету + заливка от краёв
color.ts доминирующие цвета, названия цветов по-русски
data/ SQLite: схема, миграции, репозитории
services/ вырезание, распознавание, файлы (провайдеры за интерфейсом)
state/ zustand-стор
docs/ продуктовый и технический разбор
Админка
Статистика по пользователям живёт по адресу https://djitrikwardrobe.duckdns.org/admin/ и закрыта паролем (HTTP Basic, bcrypt на стороне Caddy). Отдельного домена не нужно: страница отдаётся из /opt/wardrobe/site/admin/, данные — из GET /api/admin/stats, куда Caddy подставляет секретный заголовок только после успешной авторизации.
Считается: пользователи (всего и с данными), вещи, коллажи, картинки (штук и мегабайт), вещи с точками посадки, новые пользователи за 24 часа и 7 дней, активные за 24 часа и 7 дней (по времени последней синхронизации), разбивка по категориям, таблица топ-пользователей, регистрации и добавленные вещи по дням. Страница сама обновляется раз в 15 секунд.
Документация
- [
docs/01-product.md](docs/01-product.md) — зачем это, для кого, объём MVP, метрики, монетизация, конкуренты. - [
docs/02-architecture.md](docs/02-architecture.md) — стек и почему он, схема данных, синхронизация, приватность, CI/CD. - [
docs/03-ai-pipeline.md](docs/03-ai-pipeline.md) — вырезание фона, мультиракурс, авто-теги, генеративная примерка, аватар, стоимость. - [
docs/04-fitting-engine.md](docs/04-fitting-engine.md) — как именно вещь садится на фигуру: координаты, опорные точки, TPS, слои, ограничения. - [
docs/05-roadmap.md](docs/05-roadmap.md) — этапы, сроки, команда, бюджет, риски.
Ограничения текущей версии
- «Оставить» возвращает пиксели из исходного вырезания; то, что алгоритм удалил ещё до кисти, вернуть нельзя — для этого нужен исходный снимок.
- Фото-блоки вставляются как есть: кроп и форма (круг, арка) пока не поддерживаются.
- Экспорт делает снимок листа как есть: с разрешением экрана, без выбора фона и размера.
- В коллаже вещи располагаются вручную; авто-раскладка «красиво по сетке» — заготовка на будущее (
collagePlacement). - Режим «Манекен» — 2.5D: вещь деформируется по опорным точкам, но не оборачивается вокруг тела. Для честного 3D нужны 3D-модели одежды (см.
docs/04-fitting-engine.md). - Вырезание фона лучше всего работает на однотонном контрастном фоне — приложение прямо просит об этом в камере. Сложные фото (пёстрый фон, мех, стекло) стоит отправлять в облачную модель.
- Опорные точки вещи расставляются автоматически по шаблону категории; ручной редактор точек — следующий шаг.
- Нет аккаунтов: данные живут на устройстве. Это осознанно для MVP — синхронизация добавляется после проверки ретеншена.
01 · Продукт
01. Продукт
В одном абзаце
«Гардероб» — это каталог собственных вещей человека, устроенный как Farfetch: белый фон, тонкие линии, вещь как товар с карточкой и характеристиками. Поверх каталога — конструктор коллажей: из вырезанных вещей собираются раскладки на белом листе (образ, капсула, «что взять в поездку»), которые можно сохранять и позже показывать. Дополнительный режим — манекен по своим пропорциям, чтобы вещь можно было примерить, а не только разложить.
Проблема
- Люди не помнят, что у них есть: в среднем носится 20–30 % гардероба, остальное лежит.
- Покупки дублируются: «нечего надеть» при полном шкафу.
- Существующие приложения для гардероба требуют много ручного труда: вырезать фон, вручную разметить категорию, цвет, сезон. Через 2–3 недели такого ввода пользователь бросает приложение.
Три барьера, из-за которых гардеробные приложения не выживают:
- Трение при добавлении вещи. Если вещь добавляется дольше 30 секунд — её не добавят.
- Качество вырезания. Криво вырезанная вещь на белом фоне выглядит как мусор, и это разрушает доверие ко всему приложению.
- Вещь некуда «приложить». Каталог сам по себе — склад. Ценность появляется, когда из вещей можно быстро собрать образ.
Наш продукт бьёт во все три: съёмка 10 секунд, автоматическое вырезание и разметка, мгновенный коллаж, а для «как это на мне» — режим манекена.
Конкуренты и чем мы отличаемся
| Продукт | Сильная сторона | Слабость, которую мы используем |
|---|---|---|
| Farfetch / SSENSE | Эталон визуального языка каталога | Это чужой гардероб, а не ваш |
| Whering | Сообщество, масштаб, бесплатность | Много ручной разметки; образы — плоский коллаж |
| Acloset | Аккуратный вид, AI-стилист | Одежда не «садится» на фигуру |
| Stylebook | Гибкость и детальность | Высокий порог входа, устаревший UX |
| Indyx | Платный человеческий стайлинг | Дорого, не массово |
Дифференциатор: качество каталога уровня люксового e-commerce + коллаж в один тап + опциональная посадка на фигуру. Красивый каталог сам по себе удерживает: людям нравится смотреть на свои вещи, разложенные как в магазине.
Визуальный язык
Референс — Farfetch. Это не «минимализм вообще», а конкретные правила:
| Решение | Значение |
|---|---|
| Фон | чистый белый #FFFFFF, без градиентов и теней |
| Текст | почти чёрный #141414, вторичный — #707070 |
| Линии | hairline #E3E3E0 вместо рамок и карточек |
| Скругления | почти нулевые: кнопки и плитки прямоугольные, круглые только иконки и FAB |
| Типографика | системный гротеск; заголовки 22–26, подписи 10–12 капсом с трекингом 1.3 |
| Плитка товара | картинка 3:4 на светло-сером #F6F6F4, под ней название и категория капсом |
| Навигация | текстовые табы с подчёркиванием активного, без «пилюль» |
| Кнопки | чёрная заливка во всю ширину, белый капс-текст |
| Изображения вещей | всегда на светлом фоне, с воздухом вокруг, без обводок |
Правило, которое важнее остальных: никакого «дизайна ради дизайна». Если элемент не помогает выбрать вещь или собрать коллаж — его нет.
Сценарии
1. «Собрать образ» (главный, ежедневный)
Утро. Открыл → «Коллажи» → «Создать коллаж» → тапнул косуху, платье, сапоги, сумку → они разложились по сетке → поправил композицию → сохранил. 30–60 секунд. Цель — довести до одного тапа: готовый коллаж «образ дня» по погоде (post-MVP).
2. «Добавить новую вещь» (еженедельно, сезонно)
Купил футболку → «+» → снял на кровати → приложение вырезало фон, определило цвет и категорию → поправил название → вещь в каталоге. Цель — 15 секунд от открытия камеры до сохранения.
3. «Посмотреть на свой гардероб как на магазин» (ежедневно, пассивно)
Открыл каталог, полистал сетку, отфильтровал «обувь», нашёл забытые ботинки. Ценность — не действие, а ощущение порядка: вещи разложены красиво и по категориям, как на витрине.
4. «Не купить лишнего» (перед шопингом)
В магазине: есть ли у меня похожее? Что с этим сочетается? Post-MVP — «карманный стилист»: загрузил фото вещи в магазине — приложение говорит, с чем из имеющегося она сочетается и не дубль ли это.
5. «Собрать чемодан» (редко, но с высоким удержанием)
Выбрал даты и погоду — приложение предлагает капсулу из имеющихся вещей. Post-MVP.
Границы MVP
Входит:
- каталог в стиле люксового e-commerce: сетка, поиск, фильтры, карточка вещи с характеристиками;
- добавление вещи камерой или из галереи, локальное вырезание фона;
- автоопределение категории, цвета, сезона, «теплоты»;
- коллаж: свободное размещение вещей на белом листе, перетаскивание, щипок, поворот, порядок слоёв;
- режим «Манекен»: фигура по своим обхватам, авто-посадка вещей по опорным точкам;
- сохранение коллажей, полностью офлайн, без регистрации.
Не входит (осознанно):
| Что | Почему не сейчас |
|---|---|
| Экспорт коллажа картинкой и шаринг | Следующий шаг: нужен снимок канваса и системный шаринг |
| 3D-модели одежды | Нужны 8+ ракурсов или ручное моделирование — убивает главный сценарий (быстрое добавление) |
| Фотореалистичный рендер образа | Дорого ($0.02–0.1 за картинку), медленно (5–20 с), требует GPU; сначала проверяем, нужен ли он вообще |
| Соцсеть, лента, лайки | Отвлекает от ядра, требует модерации и критической массы |
| Шопинг и партнёрские ссылки | Другая бизнес-модель, другая команда |
| Синхронизация и аккаунты | Усложняет MVP; сначала проверяем ретеншен на локальной версии |
| Распознавание одежды на фото человека | Отдельная тяжёлая задача, не нужна для базового цикла |
Ключевой цикл и метрики
Цикл: добавил вещь → собрал коллаж → сохранил/показал → вернулся добавить новую вещь.
| Метрика | Определение | Цель MVP |
|---|---|---|
| Активация | Пользователь добавил ≥ 5 вещей И собрал ≥ 1 коллаж в первую сессию | 40 % |
| Time-to-add | От нажатия «+» до сохранённой вещи | < 20 с |
| Успешное вырезание | Доля вещей, сохранённых без пересъёмки | > 85 % |
| D7 retention | Вернулся на 7-й день | > 25 % |
| Коллажей на пользователя в неделю | Среднее | > 2 |
| Вещей на пользователя | Через 2 недели | > 25 |
Метрики-диагностики: доля пересъёмок, доля ручных правок категории (если высокая — плохо работает распознавание), время сборки коллажа (если больше 2 минут — неудобный редактор).
Монетизация
Freemium-подписка (ориентир $4.99–7.99 / мес):
- бесплатно: до 60 вещей, манекен, образы без лимита;
- подписка: фотореалистичные рендеры образа, погодные подсказки, капсулы и чемодан, расширенная статистика «цена носки», неограниченный гардероб.
Логика: платить готовы за результат (красивый рендер «как это на мне»), а не за хранение. Поэтому генеративный рендер — платная функция, а не бесплатная.
Риски продукта
| Риск | Как проверяем/снижаем |
|---|---|
| Люди не хотят фотографировать всю одежду | Тест на 15 пользователях: сколько вещей добавят за первую неделю без напоминаний |
| Манекен «не похож на меня» — и доверие падает | Дать выбор: абстрактный манекен по пропорциям ИЛИ фотореалистичный аватар по фото (этап 2) |
| Вырезание недостаточно хорошее для тёмных/пёстрых вещей | Гайд по съёмке + облачный fallback + ручная кисть |
| Приложение превращается в «ещё один каталог» | Ежедневный сценарий «образ дня» и напоминания, а не только хранение |
Что проверить до разработки (2 недели)
- 15 интервью: как сейчас выбирают одежду, что мешает, фотографируют ли вещи.
- Тест «бумажного прототипа»: показать 3 экрана (камера, гардероб, манекен) — понятно ли без объяснений.
- Golden set из 100–300 реальных фото вещей: на нём измеряем качество вырезания, прежде чем строить всё остальное.
- Проверить готовность платить: лендинг с ценой и кнопкой «оставить почту».
02 · Архитектура
02. Архитектура
Принципы
- Local-first. Всё работает без сети и без аккаунта. Сервер — ускоритель и синхронизация, а не условие работы.
- Ядро без фреймворка. Вся математика примерочной — чистый TypeScript без React Native. Её можно тестировать в Node, переиспользовать в вебе и позже вынести на сервер.
- Провайдеры за интерфейсом. Вырезание фона и распознавание — это interchangeable-сервисы: локальный алгоритм, свой GPU-сервис или сторонний API. Приложение не знает, кто именно отвечает.
- Считать на устройстве всё, что можно. Ноль сетевых задержек, ноль счетов за API, работает в метро.
Стек и обоснование
| Слой | Выбор | Почему | Альтернатива |
|---|---|---|---|
| Клиент | Expo SDK 58, RN 0.88, New Architecture | OTA-обновления, EAS Build без локального Xcode/Android Studio, один язык с бэкендом | Flutter (сильнее в 3D, но медленнее в итерациях и хуже переиспользует TS-ядро), нативные два приложения (дорого) |
| Роутинг | expo-router | Файловые экраны, deep links, typed routes | react-navigation напрямую |
| Рендер примерочной | @shopify/react-native-skia | GPU, треугольные меши (Vertices), шейдеры, картинки как текстуры | WebGL/three.js (тяжелее, 3D не нужен), SVG (медленно на мешах) |
| Жесты и анимации | Reanimated 4 + worklets | Перетаскивание на UI-потоке, без ре-рендеров React | PanResponder (дёргается) |
| Хранение | expo-sqlite (WAL) | Транзакции, индексы, нормальные запросы, офлайн | AsyncStorage (не для 500+ вещей), MMKV (ключ-значение) |
| Состояние | zustand | Минимум кода, нет провайдеров, легко тестировать | Redux Toolkit (тяжелее), Context (ре-рендеры) |
| Валидация | zod | Проверка ответов внешних API до попадания в базу | ручные проверки |
| Камера | expo-camera | Достаточно для фото, Config Plugin для разрешений | react-native-vision-camera (нужен для realtime-обработки кадров, этап 2) |
Почему не Flutter. Flutter объективно сильнее в кастомном 2D/3D-рендере, и если продукт уйдёт в честное 3D с тканью — это аргумент мигрировать. Но MVP — это 2.5D-композитинг и много продуктовой логики. React Native + Skia даёт 90 % нужного рендера за 30 % времени, а TypeScript-ядро потом можно переиспользовать где угодно.
Слои и направление зависимостей
app/ экраны, навигация
↓
components/ UI-кит, Skia-канвас, манекен
↓
state/ zustand: гардероб, профиль, образы
↓
services/ cutout, vision, files, (позже) sync
↓
data/ SQLite: схема, миграции, репозитории
↓
core/ чистая математика: TPS, меши, антропометрия, вырезание
Правило: core/ не импортирует ничего из React Native и не знает про базу. data/ не знает про React. Экраны не работают с SQL напрямую.
Схема данных
garments(id, name, category, image_uri, thumb_uri, image_width, image_height,
rig JSON, tags JSON, favorite, wear_count, created_at, updated_at)
outfits(id, name, created_at, updated_at, last_worn_at)
outfit_items(id, outfit_id, garment_id, layer, transform JSON, visible, mirrored, position)
settings(key, value) -- профиль тела, флаги онбординга
Решения:
- **
rigиtags— JSON.** Это вложенные структуры (до 24 точек, до 4 цветов, сезоны), которые читаются целиком вместе с вещью. Отдельные таблицы дали бы JOIN-ы без выгоды. Цена — нельзя индексировать по цвету; когда понадобится поиск по цвету, добавим денормализованные колонкиprimary_color,warmth. - Порядок слоёв не хранится числом.
layer— это enum (lower,upper,knit,outer,shoes…), а z-порядок вычисляется функциейLAYER_Z. Так правила («куртка всегда выше свитера») живут в коде, а не в данных, и не портятся при редактировании. - **
position** сохраняет порядок внутри слоя — важно для нескольких вещей одного типа. - Пути к файлам детерминированные:
documentDirectory/garderob/garments/<id>.png. Это позволяет позже восстановить ссылки после переустановки/синхронизации: id — он же ключ в облаке. - Миграции через
PRAGMA user_version. Добавление таблицы = новая константаMIGRATION_Nи инкремент версии.
Синхронизация (этап 2, когда появится бэкенд)
Контекст: один пользователь, 2–3 устройства, картинки по 1–3 МБ, правки редкие.
- Бэкенд: Supabase (Postgres + Auth + Storage + RLS) или собственный Postgres + S3-совместимое хранилище. Edge-функции для тяжёлых вызовов (cutout, VLM).
- Outbox. Любая локальная запись пишется в
sync_outbox(entity, entity_id, op, payload, created_at)в той же транзакции. Отдельный воркер отправляет пачками и помечает отправленные. Гарантия «не потеряли правку». - Версии. У каждой строки
rev INTEGERиdeleted_at. Сервер принимает запись, только еслиrevбольше текущего — идемпотентно при ретраях. - Конфликты. Last-write-wins по строке: для одного пользователя этого достаточно. Исключение —
outfit_items: они синхронизируются как «набор образа целиком» (replace-all), поэтому конфликт разрешается поoutfits.updated_at. - Картинки грузятся асинхронно после строки, по content hash; на клиенте показывается локальный файл. Скачивание — по требованию, сначала миниатюра.
- Курсор — серверное время последнего pull; клиентские часы не используются.
Приватность и безопасность
Фото одежды — чувствительные данные: по ним видно, что человек носит, где живёт (по фону), какого он телосложения.
- По умолчанию — только на устройстве. Облачные провайдеры вырезания/распознавания выключены, пока пользователь явно не согласится (в MVP их вообще нет).
- Шифрование: iOS — Data Protection (файлы недоступны при заблокированном экране), Android —
EncryptedFile/Keystore. Пароли/токены — Keychain/Keystore. - Минимум данных на сервере: облако получает только вырезанные PNG и теги, оригинальные фото остаются локально.
- Юрисдикция. Если целевой рынок — РФ, персональные данные хранятся в РФ (152-ФЗ): Yandex Cloud / VK Cloud, уведомление РКН, политика обработки. Если глобально — EU-регион (GDPR): DPA с Supabase/AWS, право на удаление, экспорт данных.
- Удаление аккаунта — каскадное: строки в БД + объекты в Storage + анонимизация аналитики. Пользователь должен получить это одной кнопкой.
- Обучающие данные: в политике явно указать, что фото не используются для обучения моделей. Это конкурентное преимущество, а не формальность.
Производительность
| Что | Решение |
|---|---|
| Вырезание фона | Работаем на изображении ≤ 900 px по длинной стороне (~1 Мпикс). JS-проходы по пикселям: 150–400 мс на среднем устройстве. Если станет мало — вынести в нативный модуль (Vision / ML Kit) или в worklet |
| Канвас | Меши считаются в useMemo и пересчитываются только при смене профиля/рига. Перетаскивание — на UI-потоке, без ре-рендера |
| Память | Одна вещь = PNG до 1024 px (~200–600 КБ). Для гардероба 300 вещей — ~150 МБ, поэтому миниатюры 256 px для сетки (этап 2) |
| Списки | До 300 вещей хватает FlatList; больше — FlashList |
| Холодный старт | Инициализация БД + чтение профиля параллельно, сплэш не держим дольше 300 мс |
Наблюдаемость
- Sentry: крэши, ANR, медленные транзакции, breadcrumbs «какой шаг конвейера упал».
- PostHog/Amplitude, ключевые события:
garment_added {provider, cutout_quality, duration_ms, category}garment_retake {reason}outfit_created {items_count, duration_ms}outfit_saved,outfit_sharedbody_profile_updated- Метрика качества вырезания в проде: доля
garment_retake+ ручные правки категории.
CI/CD
- EAS Build — облачные сборки iOS/Android без локальных тулчейнов.
- EAS Update — OTA для JS-правок между релизами (не для нативных изменений).
- GitHub Actions:
pnpm typecheck,pnpm test:core, линт, сборка preview на PR. - Каналы:
development(внутренние),preview(TestFlight/Internal testing),production. - Версионирование:
app.jsonversion + autoIncrement для build number.
Что менять при росте
- ML-сервис на GPU (Modal/RunPod/Fly.io) с очередью и вебхуками: cutout → качество, VTON → рендеры.
- Нативный модуль для сегментации (iOS Vision, Android ML Kit) — быстрее и точнее JS-алгоритма, работает в реальном времени.
- CDN для картинок и миниатюр.
- Разбиение ядра на пакет
@garderob/coreдля веба и сервера.
03 · AI-конвейер
03. AI-конвейер
Здесь описано, что происходит с фотографией от нажатия на кнопку до вещи на манекене, и какие модели/сервисы для этого нужны. Порядок именно такой: сначала дешёвое и обязательное, потом дорогое и опциональное.
фото → контроль качества кадра → вырезание фона → нормализация PNG
→ распознавание (теги) → опорные точки (шаблон категории) → вещь в гардеробе
↘ по запросу: генеративный рендер образа
1. Захват и контроль качества
Мусор на входе даёт мусор на выходе, поэтому камера не просто снимает — она проверяет кадр.
Что просим у пользователя (и показываем в камере):
- однотонный фон, контрастный вещи (белая футболка — на тёмном, чёрные брюки — на светлом);
- ровный свет, без прямой лампы и жёстких теней;
- вещь целиком в кадре, расправлена, без заломов;
- съёмка сверху, телефон параллельно поверхности.
Автопроверки кадра (на устройстве, до отправки):
| Проверка | Как | Действие |
|---|---|---|
| Резкость | дисперсия лапласиана по даунскейлу | «Кадр смазан» |
| Пересвет/недосвет | гистограмма, доля пикселей у 0 и 255 | «Слишком тёмно/светло» |
| Пёстрый фон | дисперсия цвета в рамке кадра | «Фон слишком пёстрый — подложите простыню» |
| Тень | градиент яркости по фону | «Уберите тень от телефона» |
| Заполнение кадра | bbox после сегментации | «Вещь слишком мелкая в кадре» |
Эти проверки стоят копейки (те же проходы по пикселям, что и вырезание) и снимают 80 % неудачных добавлений.
2. Сколько ракурсов реально нужно
Пользователь предполагает, что «придётся фотографировать с разных ракурсов». Это верно не всегда, и важно не перегрузить его.
| Режим | Ракурсы | Зачем |
|---|---|---|
| 2D-примерка (MVP) | 1, фронт | Достаточно: вещь деформируется по опорным точкам |
| Расширенная карточка | + спинка, + деталь ткани | Принт на спине, фактура, состав — для описания и поиска |
| 3D-вещь | 8–30 ракурсов + фотограмметрия | Честное 3D, оборачивание вокруг тела. Это отдельный продукт, не MVP |
Решение: MVP просит один кадр. Спинку и деталь — опционально, кнопкой «добавить ракурс», они не блокируют сохранение и используются для тегов и будущего рендера. 3D-реконструкцию вещи не делаем: пользователь не будет снимать свитер 20 раз, а без этого 3D-модель не получится.
3. Вырезание фона
Это самая ответственная часть: плохой край убивает впечатление от всего приложения.
Уровни (в порядке включения)
| Уровень | Решение | Качество | Стоимость | Когда |
|---|---|---|---|---|
| 0. Локальный алгоритм (реализован) | медианный цвет рамки + заливка от краёв + эрозия/despill | хорошо на однотонном фоне | 0 | MVP, всегда как fallback |
| 1. Нативная сегментация | iOS 17+ VNGenerateForegroundInstanceMaskRequest; Android ML Kit Subject Segmentation / Gemini | отлично на предметах | 0 | сразу после MVP |
| 2. Облачная модель | BiRefNet / SAM 2–3 на своём GPU, либо Photoroom / remove.bg API | лучшее на сложных фото | $0.005–0.05 за фото | по кнопке «улучшить» или автоматически при низком качестве |
Почему не начать сразу с облака: задержка 1–3 с на каждую вещь и зависимость от сети убивают сценарий «добавить 20 вещей за вечер». Локальный путь даёт 1–2 с и ноль счетов, а на правильном фоне результат сопоставим.
Постобработка (обязательна при любом провайдере)
- Эрозия альфы на 1 px — убирает светлый ореол от фона.
- Despill — для полупрозрачных пикселей цвет восстанавливается как
C = (P − (1−α)·B) / α, иначе по краю остаётся цветной контур. - Сглаживание края (box blur по альфе) — против «лесенки».
- Обрезка по bbox с полями 2–3 px — вещь занимает весь кадр карточки.
- Нормализация: длинная сторона ≤ 1024 px, PNG (альфа обязательна), sRGB.
Ручная страховка
Кисть «стереть/вернуть» поверх альфы. Автоматика ошибается на 10–15 % вещей (мех, кружево, прозрачные ткани, блики). Без ручной правки пользователь просто выбросит вещь.
Как измеряем качество
- Golden set: 300 реальных фото (разные фоны, ткани, принты, цвета).
- Метрики: IoU маски, F1 по краю, доля «принято без правок».
- Прогон на каждом изменении алгоритма и при смене провайдера.
- В проде: доля пересъёмок и правок кистью по каждой категории.
4. Распознавание вещи (теги)
Нужно, чтобы пользователь не заполнял 10 полей руками.
**Схема ответа (совпадает с src/core/tags.ts):**
{
"name": "белая рубашка оверсайз",
"tags": {
"category": "top",
"subcategory": "рубашка",
"colors": ["#f2f2ef", "#d8d5cc"],
"pattern": "solid",
"material": "хлопок",
"seasons": ["spring", "summer", "autumn"],
"warmth": 2,
"formality": 4
}
}
Как получаем:
- VLM со structured output (JSON Schema): GPT-4o-mini / Gemini Flash / Qwen-VL — что дешевле и доступно на рынке. Важно:
temperature 0–0.2, few-shot примеры, строгая схема, ответ валидируется zod. - Промпт содержит категорию, которую пользователь уже выбрал (если выбрал) — это резко повышает консистентность.
- Кэш по хешу изображения: повторная обработка не стоит денег.
- Стоимость: $0.0005–0.003 за вещь (≈ $0.1–0.3 на гардероб из 100 вещей, единоразово).
Локальная альтернатива (реализована): доминирующие цвета гистограммой + разумные значения по категории. Бесплатно и мгновенно, но не понимает материал и фасон. Используется, когда сервис не настроен.
Эмбеддинги (этап 2): текст-эмбеддинг описания каждой вещи → «похожие вещи», «собери капсулу», «не дубль ли это» при покупке.
5. Персональный аватар
Три уровня, включаются по возрастанию сложности:
| Уровень | Что это | Плюсы | Минусы |
|---|---|---|---|
| A. Параметрический манекен (реализован) | силуэт строится из обхватов и роста | мгновенно, бесплатно, офлайн, полностью управляемо | стилизованный, не «фото» |
| B. Фотореалистичный аватар | 1–3 фото человека → генерация full-body изображения (Photoroom, генеративные модели, Meshcapade/Avaturn) | «это я» | нужен облачный GPU, вопросы приватности, артефакты |
| C. 3D-аватар (SMPL) | параметрическая 3D-модель тела | честная антропометрия, можно 3D-одежду | нужны 3D-модели одежды, тяжёлый рендер |
Решение: A сейчас, B — как платная функция после MVP, C — только если продукт уйдёт в 3D. Для A важна не «реалистичность», а узнаваемость пропорций: пользователь двигает ползунки и видит, что силуэт меняется как его собственный.
6. Генеративная примерка (фотореалистичный рендер)
Не в MVP, но архитектуру надо заложить сразу, иначе потом больно.
Как работает: VTON-модель получает изображение человека (или сгенерированной модели) и изображение вещи, возвращает человека в этой вещи. Мульти-вещь — последовательные проходы: сначала верх, потом низ, потом верхняя одежда, с масками регионов.
Кандидаты: FASHN, Photoroom, Google Vertex AI Virtual Try-On, self-hosted IDM-VTON / CatVTON / OOTDiffusion на Replicate/fal/Modal.
Что важно знать заранее:
- Латентность 5–20 с → только асинхронно: задача в очереди, пуш «образ готов».
- Цена $0.02–0.10 за рендер → это платная функция, а не бесплатная.
- Модель галлюцинирует: теряет принт, меняет крой, добавляет складки. Поэтому рендер всегда подписан как «визуализация», а рядом остаётся честный 2D-образ.
- Лицензии: у части API запрещено использовать для коммерческих примерок или тренировать на результатах — проверить до интеграции.
- Приватность: фото человека уходит в облако → отдельное согласие, возможность удалить.
Архитектура: клиент → edge-функция render-outfit → очередь → воркер с GPU → Storage → пуш. Клиент получает job_id и подписан на статус. Никаких синхронных запросов из приложения.
7. Стоимость на активного пользователя
Оценка на месяц (100 вещей, 30 образов, 10 генеративных рендеров):
| Статья | Стоимость |
|---|---|
| Вырезание (локально) | $0 |
| Распознавание: 100 вещей × $0.001 | $0.10 (единоразово) |
| Генеративные рендеры: 10 × $0.05 | $0.50 |
| Хранение: 100 PNG × 0.5 МБ | ~$0.01 |
| Инфраструктура (Supabase, Sentry, аналитика) | ~$0.05–0.15 на пользователя при базе < 10k |
Итого переменные расходы ≈ $0.6–1.0 на активного пользователя в месяц. При подписке $4.99 маржа здоровая, если не давать рендеры без лимита.
8. Чего не делать
- 3D-реконструкция вещи по фото. Дорого, медленно, требует много ракурсов. Пользователь не будет.
- Собственная модель сегментации с нуля. Использовать готовые (BiRefNet/SAM/Vision/ML Kit), дообучать только если упрёмся.
- Realtime-примерка на видео. Отдельная тяжёлая задача, не нужна продукту.
- Обучение на данных пользователей. Юридически и репутационно дорого, выгоды на старте нет.
04 · Движок посадки
04. Движок посадки
Как вещь, снятая на телефон, оказывается на листе коллажа и — в режиме «Манекен» — садится по фигуре, а не просто масштабируется.
Код: apps/mobile/src/core/ (body.ts, rig.ts, tps.ts, mesh.ts, outfit.ts), рендер: src/components/OutfitCanvas.tsx.
0. Два режима одного листа
| Режим | Что происходит | Зачем |
|---|---|---|
| Коллаж (по умолчанию) | белый лист, вещи кладутся свободно: перетаскивание, щипок, поворот, порядок слоёв | собрать образ/капсулу как мудборд |
| Манекен | тот же лист, но с фигурой: вещи автоматически деформируются по опорным точкам и сортируются по слоям одежды | «как это будет на мне» |
В обоих режимах одна система координат, поэтому переключение не ломает данные: при смене режима вещи переставляются (collagePlacement в коллаже, identity-трансформ в манекене — дальше их ставит TPS).
1. Система координат
Всё считается в виртуальном канвасе 1000 × 1500 (портрет 2:3), затем масштабируется под ширину экрана. Так пропорции не зависят от устройства, а тесты работают с целыми числами. Формат 2:3 выбран под коллаж: он читается как вертикальный постер и целиком влезает на экран телефона.
- Фигура занимает
y ∈ [50, 1450],xсимметрично вокруг 500. - Вещь приходит как PNG с прозрачным фоном, её координаты — пиксели изображения.
- Опорные точки вещи заданы в пикселях изображения, опорные точки фигуры — в канвасе.
2. Антропометрия → силуэт
Пользователь задаёт 5 чисел: рост, плечи, грудь, талия, бёдра. Из них строятся полуширины:
heightScale = clamp(170 / heightCm, 0.85, 1.15)
shoulderHalf = 165 · heightScale // ≈ 0.118 высоты фигуры
pxPerCm = shoulderHalf / (shouldersCm / 2)
bustHalf = clamp(chestCm · 0.16 · pxPerCm, shoulderHalf·0.55, shoulderHalf·0.86)
waistHalf = clamp(waistCm · 0.17 · pxPerCm, bustHalf·0.60, bustHalf·1.05)
hipHalf = clamp(hipsCm · 0.18 · pxPerCm, waistHalf·1.00, shoulderHalf·1.15)
thighHalf = hipHalf · 0.44
calfHalf = thighHalf · 0.62
upperArmHalf = shoulderHalf · 0.24
Коэффициенты 0.16/0.17/0.18 — перевод обхвата во фронтальную ширину (обхват ≈ π · ширина, с поправкой на то, что торс не круглый). Они подобраны так, чтобы при 88/70/96 см получалась правдоподобная фигура, и проверяются тестами на монотонность: увеличили талию — силуэт стал шире.
Базовое значение полуширины плеч (165 px при высоте фигуры 1400 px) — это 0.236 от высоты, то есть размах плеч ≈ четверть роста, как у живого человека. Первая версия использовала 62 px (0.09 высоты) — фигура получалась непропорционально вытянутой; это исправлено.
Вертикальные пропорции фиксированы (доли роста):
| Точка | Доля | Точка | Доля |
|---|---|---|---|
| макушка | 0.000 | талия | 0.360 |
| подбородок | 0.125 | бёдра | 0.460 |
| шея | 0.152 | промежность | 0.490 |
| плечи | 0.176 | колено | 0.720 |
| подмышка | 0.236 | щиколотка | 0.955 |
| грудь | 0.256 | носок | 0.990 |
Силуэт собирается из путей: торс — замкнутая Catmull-Rom кривая по 13 точкам, руки и ноги — толстые штрихи с круглыми концами (два сегмента на конечность, чтобы была видна сужающаяся голень/предплечье), голова — эллипс, волосы — 2–3 фигуры позади/поверх.
3. Опорные точки
24 точки, общие для фигуры и вещи (LandmarkId):
headTop chin neckL neckR shoulderL shoulderR armpitL armpitR
bust waistL waistR hipL hipR crotch kneeL kneeR ankleL ankleR
toeL toeR elbowL elbowR wristL wristR
У фигуры они вычисляются из метрик. У вещи — из шаблона категории: где на типичной футболке находятся плечи, проймы и низ, в долях от bbox вещи.
| Категория | Точки шаблона | Куда садится низ |
|---|---|---|
| Верх (футболка, рубашка) | горловина, плечи, проймы, низ | талия |
| Трикотаж (свитер, кардиган) | то же | бёдра |
| Верхняя одежда | плечи, проймы, борт | бёдра |
| Платье | горловина, плечи, проймы, талия, низ | колени |
| Низ (брюки, юбка) | талия, бёдра, низ | щиколотки |
| Обувь | щиколотка, носок | — |
| Сумка, аксессуар | нет (свободное размещение) | — |
Это ключевое решение: одна и та же вещь автоматически «знает», где у неё плечи, и ей не нужна ручная разметка при добавлении. Пользователь может поправить точки позже (следующий этап), но по умолчанию — ноль действий.
4. Деформация: thin plate spline
Аффинного преобразования (масштаб + сдвиг) недостаточно: у людей разная талия и бёдра, и футболка должна сузиться в талии, но остаться широкой в плечах. Нужна нелинейная деформация по опорным точкам.
TPS минимизирует энергию изгиба и точно проходит через заданные пары точек:
f(p) = a₀ + a₁x + a₂y + Σ wᵢ · U(|p − cᵢ|), U(r) = r² ln r
Коэффициенты находятся из системы:
[ K + λI P ] [ w ] [ v ]
[ Pᵀ 0 ] [ a ] = [ 0 ]
Kᵢⱼ = U(|cᵢ − cⱼ|), Pᵢ = [1, xᵢ, yᵢ]
Реализация (tps.ts):
- Нормализация координат. Перед решением точки центрируются и масштабируются в диапазон ~[−1, 1]. Без этого матрица плохо обусловлена (пиксели — сотни,
r² ln r— десятки тысяч), и решение «плывёт». - Регуляризация λ ≈ 0.002–0.004. Если пользователь поставил две точки почти в одно место, матрица вырождена. λ делает деформацию мягче и гарантирует решение; при этом опорные точки воспроизводятся с точностью ~0.01 px (проверено тестом).
- Fallback. Меньше 3 точек или вырожденная матрица → аффинное приближение (перенос + масштаб), приложение не падает.
Почему TPS, а не кусочно-аффинное по триангуляции: при 6–10 точках триангуляция даёт заметные изломы на стыках треугольников, TPS — гладкую поверхность. Цена — O(n³) на решение, но n ≤ 10 и считается один раз при изменении профиля.
5. Сетка и рендер
Вещь нельзя рисовать как один прямоугольник с текстурой — текстуру надо «натянуть» на деформированную поверхность. Поэтому:
- Вокруг вещи строится регулярная сетка
cols × rows(плотность зависит от размера:cols ≈ w/110, от 4 до 16;rows ≈ h/110, от 6 до 24). - Каждый узел прогоняется через TPS → координаты в канвасе.
- Текстурные координаты узлов остаются в пикселях исходной картинки.
- Skia рисует это как
VerticesсImageShader— GPU-текстурированные треугольники.
Итог: вещь изгибается по фигуре, край остаётся резким (текстура сэмплируется с линейной фильтрацией), всё рисуется в 60 fps.
6. Трансформации поверх деформации
Каждая вещь дополнительно имеет transform { x, y, scale, rotation }. Он применяется вокруг центра bbox вещи:
translate(x + cx, y + cy) · rotate · scale · translate(−cx, −cy)
где (cx, cy) — центр bbox. Такая семантика позволяет:
- свободным вещам (сумка, аксессуар) задавать позицию центра в канвасе;
- масштабировать вещь от центра, чтобы она не «уезжала»;
- двигать пальцем, не меняя посадку.
7. Слои
Порядок отрисовки задаётся не пользователем, а категорией:
under 5 → lower 10 → full(платье) 25 → upper 30 → knit 40 → outer 50 → shoes 55 → bag 60 → accessory 70
Так куртка всегда выше свитера, свитер выше рубашки, обувь выше брюк. Пользователь может скрыть вещь или убрать её, но не «сломать» физику слоёв. Валидатор образа дополнительно подсказывает неочевидное (платье + низ, две вещи в слое «верх»), но не блокирует сохранение.
8. Честные ограничения 2.5D
| Ограничение | Что видно | Как решать |
|---|---|---|
| Нет окклюзии конечностей | если рука должна быть поверх вещи (руки в карманах, скрещены), вещь всё равно сверху | разбить аватар на части (торс, плечо, предплечье) и сортировать по z вместе с вещами; маски окклюзии для рукавов |
| Рукав не оборачивается вокруг руки | рукав выглядит плоским | либо рисовать рукав отдельным слоем поверх руки, либо 3D |
| Ткань не симулируется | нет складок от позы и натяжения | для 2.5D — нарисовать тени/складки в текстуре; для честного — cloth sim |
| Сильное расхождение размеров | вещь растягивается, а не «мала» | поставить пользователю размер вещи (XS–XXL) и ограничивать масштаб; подсвечивать «не сядет» |
Путь к 3D (если продукт туда пойдёт): SMPL-X как тело → параметрические 3D-модели одежды (CLO/Marvelous Designer, шаблоны по категориям) → скиннинг по телу → cloth simulation на устройстве (или запечённая анимация). Это в 10 раз дороже по контенту: на каждую вещь нужна 3D-модель, а не фото. Поэтому 2.5D — правильная точка старта.
9. Инварианты и тесты
npm run test:core проверяет:
- TPS точно воспроизводит опорные точки (ошибка < 0.01 px).
- TPS переносит и точки между опорами, а не только их.
- Сетка:
(cols+1)(rows+1)вершин,2·cols·rowsтреугольников. - Деформированная сетка накрывает фигуру, а не исходный прямоугольник.
- Плотность сетки ограничена сверху (защита от тормозов).
- Монотонность антропометрии: больше талия → шире силуэт; выше рост → уже в фиксированном канвасе.
- Симметрия и порядок опорных точек (плечи выше талии, талия выше бёдер…).
- Шаблоны есть у всех категорий с одеждой.
- Слои: платье между низом и трикотажем.
- Валидатор образа ловит отсутствующую вещь и конфликты.
Это тесты на математику, а не на UI: они гоняются в Node за 50 мс и ловят регрессии при изменении коэффициентов.
05 · План
05. План
Где мы сейчас
Готов рабочий прототип ядра: путь «сфотографировал → вещь в гардеробе → собрал образ на своём манекене» реализован целиком, офлайн, без единого API-ключа. Это не макет: вырезание фона, антропометрия, TPS-посадка и рендер работают, математика покрыта тестами.
Что это даёт: можно за неделю показать продукт живым людям и проверить главный риск — «будут ли люди фотографировать свою одежду». Всё остальное (аккаунты, облако, платежи) добавляется поверх, не переписывая ядро.
| Блок | Состояние |
|---|---|
| Гардероб, камера, вырезание, манекен, образы | ✅ готово |
| Нативная сегментация, VLM-теги | 🔜 этап 2 |
| Аккаунты, синхронизация, аналитика | 🔜 этап 2 |
| Платежи, магазины, онбординг | 🔜 этап 3 |
| Фотореалистичный рендер, погода, капсулы | 🔜 этап 4 |
Этапы
Этап 0. Валидация — 2 недели
Цель: понять, стоит ли строить, до больших затрат.
- 15 интервью с целевой аудиторией.
- Golden set 300 фото вещей, замер качества вырезания.
- Тест прототипа на 10 людях: сколько вещей добавят, где бросают.
- Лендинг с ценой, замер готовности платить.
Выход: решение go/no-go, список 5 главных проблем UX.
Этап 1. MVP-ядро — 6 недель
Цель: приложение, которым можно пользоваться неделю и не бросить.
- Полировка камеры: автопроверки кадра, подсказки, повторная съёмка.
- Ручная кисть правки маски (без неё 10–15 % вещей не добавить).
- Редактор опорных точек вещи (сейчас только шаблон).
- Миниатюры и оптимизация памяти (300+ вещей).
- Онбординг: 3 экрана, создание «себя», первая вещь.
- Пустые состояния, ошибки, восстановление после сбоя.
Выход: внутренняя сборка, 10 пользователей, неделя использования.
Этап 2. Бета — 4 недели
Цель: выход в TestFlight / Play Internal.
- Нативная сегментация: iOS Vision, Android ML Kit, локальный алгоритм как fallback.
- VLM-теги через свой edge-сервис (категория, цвет, материал, сезон).
- Аккаунты (Apple/Google) + синхронизация local-first (outbox, LWW).
- Sentry, аналитика, события качества.
- Облачный cutout для сложных фото по кнопке «улучшить».
Выход: 100–300 бета-пользователей, метрики активации и D7.
Этап 3. Релиз — 3 недели
- Подписка (RevenueCat или нативные IAP), пейволл, восстановление покупок.
- ASO: иконка, скриншоты, описание, ключи.
- Политика конфиденциальности, удаление аккаунта, возрастной рейтинг.
- Поддержка: почта + FAQ, обработка жалоб на контент (если появится шаринг).
- App Store / Google Play review, исправление замечаний.
Выход: публичный релиз.
Этап 4. Post-MVP — 8 недель
Приоритет по данным, а не по желанию:
- «Образ дня» по погоде и календарю (главный ежедневный сценарий).
- Фотореалистичный рендер образа (платно, асинхронно).
- Капсулы и чемодан.
- Шаринг образов / совместный гардероб.
- Фотореалистичный аватар по фото.
Итого
| Длительность | Команда | |
|---|---|---|
| До беты | 12 недель | 2 RN, 1 backend/ML, 1 дизайнер (0.5), QA (0.5) |
| До релиза | +3 недели | то же |
| Post-MVP | +8 недель | 2 RN, 1 backend/ML, 1 дизайнер |
Трудозатраты до релиза ≈ 14–16 человеко-месяцев. Деньги зависят от ставок: при blended $4–6k/мес это $60–95k, при инхаус-команде — фонд оплаты труда за 4 месяца.
Инфраструктура на старте: Supabase $25–100/мес, Sentry $26/мес, аналитика $0–50/мес, GPU-сервис — по факту использования ($0, пока рендеры выключены).
Definition of Done для релиза
- Новый пользователь без подсказок добавляет 5 вещей и собирает образ за первую сессию.
- 85 %+ вещей сохраняются без пересъёмки.
- Приложение работает офлайн полностью, кроме платных рендеров.
- Холодный старт < 2 с, добавление вещи < 20 с на среднем устройстве.
- Крэш-фри ≥ 99.5 %.
- Данные удаляются по запросу, политика опубликована.
- Есть метрики активации, D1/D7/D30 и воронка добавления вещи.
Риски и что делаем
| Риск | Вероятность | Влияние | Мера |
|---|---|---|---|
| Люди не хотят фотографировать гардероб | Высокая | Критическое | Проверить на этапе 0; упростить до 1 кадра; импорт из галереи; «добавьте 5 вещей — увидите образ» |
| Вырезание плохо работает на реальных фото | Средняя | Высокое | Гайд по съёмке + нативная сегментация + облачный fallback + кисть |
| Манекен «не похож на меня» | Средняя | Среднее | Ползунки пропорций, затем фотореалистичный аватар |
| Стоимость генеративных рендеров съедает маржу | Средняя | Среднее | Только по подписке, лимиты, кэш, дешёвые модели |
| Конкуренты скопируют фичу | Средняя | Низкое | Скорость итераций, качество посадки, бренд |
| App Store отклонит из-за UGC | Низкая | Среднее | Модерация, жалобы, возрастной рейтинг — до запуска шаринга |
| Один разработчик = bus factor | Высокая | Высокое | Документация (эти файлы), тесты ядра, код-ревью |
Что делать на этой неделе
- Собрать golden set из 50–100 фото реальных вещей (свои шкафы, друзья) — без него нельзя оценивать качество.
- Прогнать прототип на 5 людях: замерить time-to-add и долю пересъёмок.
- Проверить нативную сегментацию на iOS 17+ и Android: сравнить с локальным алгоритмом на golden set.
- Решить по бэкенду: Supabase или свой стек (влияет на этап 2).
- Собрать dev-build через EAS и проверить на реальных устройствах (Skia + камера).