Клонируем механику Looksy (реверс §1¾: конфиг, prewarm, fitting, polling, история, комплекты, лимиты), но на своих рельсах: серверный рендер + dashboard/tryon.py + blueprints/tryon.py + static/widgets/tryon.js. GPU — только через серверный прокси, ключ в env, дневные капы. Фото покупателей — за TTL, не в git, не в бэкапы вечно.
Магазин женской одежды вставляет одну строку в карточку товара → кнопка «Примерить онлайн» → фото покупателя → результат ~25–40 с + размер + «собери образ» + «Купить». Владелец видит в дашборде: примерки, конверсию в корзину, расход GPU-кредитов, топ-товары, логи.
Платформа: Flask/waitress на VPS, per-tenant JSON (data/<slug>/), модули через MODULE_ROUTE_PREFIXES, виджеты launcher.js/reviews.js + public JSON, тарифы free/pro/business/enterprise (без счётчиков использования). Модуля примерки нет.
Модуль tryon: настройки кнопки, сниппет, журнал заданий, статистика, лимиты (магазин/день + юзер/день=10), stub-провайдер для E2E без GPU-ключа, FASHN-клиент за флагом. Пилот на 1 магазине.
| # | Функция Looksy | Примерочная (план) | Улучшение ★ |
|---|---|---|---|
| F1 | Одна строка вставки + shop-token | tryon.js data-config=/<slug>/widget/tryon.json, секрета в браузере нет | ★ конфиг без токена вообще (public JSON), origin-check |
| F2 | Кнопка сама находит галерею | селекторы галереи в конфиге + fallback + ручной якорь data-tryon-anchor | ★ Tilda-T123 пресет из коробки |
| F3 | Согласие + гайд с good/bad фото | тексты из конфига (версионирование consent_version), примеры — URL из админки | ★ русский текст + 152-ФЗ формулировки by default |
| F4 | Загрузка фото (25 МБ, JPG/PNG/HEIC) | лимит 8 МБ MVP, ресайз на клиенте (canvas, max 1600px) до отправки | ★ клиентский ресайз режет трафик и GPU-счёт в разы |
| F5 | Prewarm при открытии карточки | нет в MVP (дорого); прогрев только после клика «Примерить» | ★ экономия холостых вызовов — осознанное отличие |
| F6 | Генерация ~24 с, polling | job: queued→processing→succeeded/failed; polling 3 с, таймаут 300 с; Idempotency-Key | ★ очередь с приоритетом + дедупликация одинаковых (вещь×фото-хэш) |
| F7 | Сайзинг (person-size-v5) | MVP: показываем размер/уверенность как вернул провайдер; свой сайзинг — фаза 2 | — |
| F8 | Ретрай (parent_generation_id), «ещё раз» | цепочка попыток в логе; 1 бесплатный ретрай при техошибке, осознанный — за квоту | ★ правило в конфиге, видно в статистике |
| F9 | Луки сохраняются (history) | «Мои луки» в localStorage + опционально серверная история 30 дней | ★ экспорт лука в корзину комплектом |
| F10 | Complete look / outfits v2 | фаза 2: подбор 4 товаров из catalog.json магазина | ★ комплекты из своего каталога (sync_catalog уже есть) |
| F11 | Результат: Купить / поделиться / скачать / оценка | то же; share-ссылка с TTL; feedback 1–5 → лог | ★ «Купить» = deep-link с utm tryon |
| F12 | Лимиты: daily 10/юзер, пакеты магазина | два уровня: посетитель/день (конфиг) + магазин/день (тариф) | ★ мягкий стоп с текстом «завтра», а не 500-я |
| F13 | Удаление фото (72 ч, DELETE) | TTL 72 ч + кнопка «удалить мои фото» + purge-cron | ★ авто-purge по cron, отчёт в админке |
| F14 | Аналитика: события воронки + Метрика | события в tryon_stats + опциональный reachGoal в Метрику магазина | ★ воронка из коробки: показ→клик→загрузка→генерация→корзина |
| F15 | Админка: брендинг, тексты, фиче-флаги, бюджет | /<slug>/tryon: настройки / задания / статистика / затраты | ★ себестоимость в ₽ рядом с каждой цифрой |
| F16 | AI-продавец (ai-seller) | вне скоупа (отдельный модуль позже) | — |
| F17 | Видео-анимация (Pro) | фаза 3, за флагом | — |
tryon_config.jsontryon_jobs.jsonl + tryon_stats.jsondata/<slug>/tryon_uploads/<job>/: src.webp, result.webp — TTL 72 ч, purge-cron ежедневно| Метод и путь | Доступ | Назначение |
|---|---|---|
| GET /tryon | admin/client_admin | админка: настройки + статистика + журнал + сниппет |
| POST /tryon/save | admin + CSRF, ≤64 KiB | сохранить конфиг (валидация как validate_config) |
| GET /widget/tryon.json | public, CORS *, ETag, 60s | конфиг для лоадера (без секретов) |
| POST /widget/tryon/jobs | public, origin-check, ≤8 МБ | создать задание: фото + товар + consent; Idempotency-Key; капы |
| GET /widget/tryon/jobs/<id> | public, signed token | статус для polling (3 с / 300 с) |
| POST /widget/tryon/jobs/<id>/feedback | public | оценка 1–5 + комментарий |
| POST /widget/tryon/events | public, 202 | события воронки (батч, как у них) |
| GET /widget/tryon/history | public, cookie-visitor | «мои луки» (30 дней) |
| POST /tryon/purge | cron/admin | чистка фото старше TTL + отчёт |
Провайдер: TRYON_PROVIDER=stub|fashn, ключ FASHN_API_KEY в env; stub возвращает демо-картинку через ~5 с (E2E без денег). Лимит магазина/день из limits(): free 10 / pro 100 / business 500 / enterprise 9999 (ключ tryon_shop_daily).
static/widgets/tryon.js (IIFE, как launcher.js)<script defer src="https://rayprism.ru/static/widgets/tryon.js" data-config="https://rayprism.ru/<slug>/widget/tryon.json"> — credentials omit, abort 8 с, MIME-check.data-tryon-anchor; MutationObserver на смену варианта товара (как их 140 мс).ym(counter,'reachGoal',...)./<slug>/tryon (templates/tryon.html)tryon_shop_daily в limits(); превышение = мягкий стоп («завтра») + событие в лог.cost_usd от провайдера × курс (конфиг платформы) → spend_rub в статистике.Риски платформы (из аудита): файлы от root → chown; restart после деплоя (Jinja-кэш); POST только без /mail/; thread-local active() — воркер вне request-контекста работает только с файлами.