- BrainTools - https://www.braintools.ru -

С помощью AI сегодня каждый может навайбкодить приложение за считанные часы. Но чтобы превратить его в рабочий PoC, нужно решить ряд архитектурных, инженерных и организационных задач. Именно они занимают гораздо больше времени и требуют уже других навыков.
В статье разберём типовую архитектуру современного AI PoC на примере моего пет-проекта MirrorVote [1] («Выбор перед зеркалом») и ответим на вопрос: если AI умеет писать код, зачем все еще нужен инженер?
AI может быстро написать код, но чтобы собрать рабочую систему, всё равно необходимо пройти основные этапы классического цикла разработки SDLC. PoC – это не промышленное решение, поэтому на каждом этапе можно сделать существенные упрощения:
Анализ требований – рассматриваем только минимальный пользовательский сценарий или MVP.
Проектирование (архитектура) – минимальная схема DB, только критичные интеграции: Auth, LLM, платежи.
Реализация – Vibe Coding, исходный код хранится в GitHub.
Тестирование – ручные проверки основных сценариев.
Развертывание – локально или на облачном VPS; deploy вручную или через GitHub Actions.
Эксплуатация – базовая observability: смотрим ошибки [2] в логах, контролируем доступность приложения и стоимость внешних сервисов.
Людям часто сложно быстро решить, какой наряд выбрать, особенно в примерочной или перед важным событием: работой, свиданием, вечеринкой. А если хочется получить совет друзей, то обычно приходится отправлять фотографии в мессенджер и получать что-то вроде: “всё нормально”.
MirrorVote [3]– это AI-помощник выбора образа, который помогает сравнить фотографии, получить AI-оценку и быстро собрать мнение друзей.
Как это работает?
Пользователь загружает несколько фотографий, система c помощью AI приводит их к единому виду – выравнивает фон, свет и позу, а затем оценивает наряды с учётом выбранного повода. Также пользователь может сгенерировать публичную ссылку для голосования:
Чтобы реализовать эту функциональность, в приложении используется следующий сценарий:
Авторизовать пользователя через Google OAuth сервер и получить JWT-токен для последующих запросов.
Загрузить фотографии для анализа.
Проверить пользователя и его доступный лимит в PostgreSQL.
Вызвать LLM для обработки фотографий, анализа образов и формирования рекомендаций.
Сохранить обработанные изображения в Storage, результаты анализа и оценки в PostgreSQL, списать использованный лимит.
Вернуть пользователю обработанные изображения и результат анализа.

Теперь посмотрим, из каких компонентов должна состоять система, чтобы реализовать этот сценарий.
На схеме представлена общая архитектура проекта MirrorVote и взаимодействие компонентов:

Давайте разберем основные компоненты решения.
Разработка велась в Claude Code, исходный код хранится в GitHub [4].
Для деплоя приложения MirrorVote используется механизм GitHub Actions.
Деплой Edge Functions в Supabase, создание структуры базы данных и последующие изменения схемы выполнялись вручную.
MirrorVote – полноценное PWA (Progressive Web App). Одна кодовая база обслуживает как веб-версию в браузере, так и приложение, установленное на смартфоне.
Браузер не обращается к внешним API напрямую. Единой точкой входа служит Nginx на VPS, который работает как web server и reverse proxy и маршрутизирует запросы к нужным сервисам. Такая схема используется в том числе для обхода проблем с доступностью Supabase для российских пользователей.
Для PoC используется managed Supabase. Это снижает объём инфраструктуры, которую приходится самостоятельно разворачивать и обслуживать.
Edge Functions (Deno) – здесь находится серверная логика [5], хранятся настройки и секретные ключи внешних API.
PostgreSQL – хранит данные приложения: пользователи, сессии, результаты анализа, лимиты, платежные события и другие сущности.
Storage – хранит исходные и сгенерированные изображения с ограничением доступа по пользователям.
Серверные функции Supabase (Edge Functions) связывают приложение с внешними сервисами.
Авторизация пользователей через Supabase Auth. Требует настройки callback URL и OAuth-провайдера, в нашем случае это Google OAuth.
Cерверная функция создаёт платёж и принимает webhook о его результате.
Cерверная функция формирует системный промпт, передаёт изображение пользователя в модель и получает результат анализа. За использование AI платим по фактическому потреблению API.
Чтобы реализовать эту архитектуру на практике, пришлось решить еще несколько организационных и инфраструктурных задач.
Подключить приём платежей. Для российского проекта удобно использовать ЮKassa. Если подключаться как физлицо, самый простой вариант – зарегистрироваться в налоговой как самозанятый. Далее необходимо подготовить работающий лендинг с описанием услуги, актуальными ценами, контактами и реквизитами и пройти проверку ЮKassa. После этого получаем данные для интеграции с API.
Зарегистрироваться в OpenRouter и получить API key для вызова LLM. Для работы с платными моделями необходимо пополнить баланс. Оплата зарубежного сервиса из России – это отдельный квест.
Создать проект в Supabase и получить параметры подключения. У Supabase есть бесплатный тариф, которого достаточно для PoC.
Настроить авторизацию пользователей через Google OAuth. Для этого предварительно необходимо создать и настроить учетные данные в Google Cloud Console.
Арендовать VPS у облачного провайдера. Для MirrorVote я использовал Selectel. Он оказался не самым дешёвым вариантом, но надежность и поддержка на высоте.
Зарегистрировать домен и настроить DNS. Домен и DNS-зона MirrorVote также размещены в Selectel.
Получить TLS-сертификат для HTTPS. Для MirrorVote используется бесплатный Let’s Encrypt через Certbot. Стандартный сертификат Let’s Encrypt действует 90 дней, поэтому важно настроить автоматическое продление.
При разработке и настройке PoC важно заранее учесть несколько инженерных моментов, так как если их игнорировать, система может работать нестабильно, терять данные или приводить к неожиданным ошибкам и денежным потерям. Рассмотрим наиболее важные темы:
Работа с LLM и оптимизация стоимости вызовов;
Проблема блокировок – настройка Nginx;
Безопасность;
Обработка ошибок;
Observability и эксплуатация.
Для каждой задачи нужно сформировать системный промпт и передать необходимый контекст. В нашем случае контекст – это повод для наряда, требования к фону, свету и позе, а также явное описание ожидаемого результата. Для анализа нарядов задаётся структура ответа в формате JSON. Также нужно выбрать LLM-модели с подходящим соотношением качества и стоимости. В MirrorVote используются две модели:
google/gemini-2.5-flash-image (Nano Banana) – для обработки и генерации изображений;
google/gemini-2.5-flash – для анализа нарядов и формирования рекомендаций.
Для анализа выбран Gemini 2.5 Flash, так как для этой задачи не нужна тяжелая reasoning-модель: необходимо быстро обработать изображение и контекст, выставить оценки и вернуть небольшой структурированный ответ.
Reverse proxy используется как единая точка входа, выполняет маршрутизацию запросов и помогает решать проблемы доступности Supabase. Клиент обращается к одному домену приложения, а Nginx направляет запрос к нужному upstream-сервису:
/ → landing
/app/* → React SPA
/supabase/* → Supabase API, Auth, Storage и серверные функции
То, что приложение работает, ещё не означает, что оно безопасно.
Пример с RLS
Один пользователь не должен иметь возможности получить фотографии другого пользователя, даже если вручную изменит ID в REST-запросе. Поэтому доступ нужно ограничивать на уровне PostgreSQL через RLS (Row Level Security). Это механизм, который ограничивает доступ к отдельным строкам таблицы в зависимости от пользователя и заданных политик доступа.
Пример со ссылкой для публичного голосования
Ссылка для публичного голосования возвращала пользователю больше информации, чем было необходимо. Формально всё работало, но пользователь с публичной ссылкой мог увидеть внутренние поля через DevTools. Для исправления нужно было не сериализовать объект целиком, а явно перечислять разрешённые поля.
Для понимания подобных рисков полезно смотреть чек-листы OWASP [6](Open Worldwide Application Security Project ). Например, для безопасности API Security. [7] В нашем случае проблема с публичной ссылкой относится к уязвимости API3:2023 Broken Object Property Level Authorization [8]. API не должен возвращать внутренние или чувствительные свойства объекта, если клиенту они не нужны. Про защиту API я подробно писал в отдельной статье: Безопасность REST API от А до ПИ [9].
Хорошая архитектура должна учитывать не только успешный сценарий, но и то, как система поведет себя при сбоях. В рамках PoC нужно предусмотреть обработку хотя бы критичных отказов:
LLM API часто возвращает временные ошибки. Например 429, 5xx или timeout. Поэтому нужно предусмотреть повторный запрос с задержкой и ограничением числа попыток.
Модели и их версии могут меняться или становиться недоступными, поэтому используемую модель нужно контролировать и периодически проверять.
Платежи – пример места, где ошибка имеет прямую денежную стоимость. Webhook может прийти повторно, поэтому его обработчик должен быть идемпотентным: повторная доставка одного и того же события не должна увеличивать лимиты пользователю.
Для PoC observability – это не обязательно централизованная система сбора логов и метрик. Достаточно уметь отвечать на несколько вопросов:
Жив ли VPS? Для этого смотрим dashboard облачного провайдера.
Доступно ли приложение пользователю? Используем внешний монитор, например, UptimeRobot.
На каком этапе упал запрос? Вручную смотрим логи Nginx, серверных функций Supabase и внешних сервисов.
Сколько стоил AI-вызов? Смотрим Activity/Usage в OpenRouter.
AI быстро пишет код, но инженерная работа начинается там, где нужно обеспечить устойчивость, безопасность и управляемость системы.
Стоимость одного пользовательского сценария складывается из обработки и анализа изображений с помощью LLM. Это не бизнес-прогноз, а приблизительная оценка, которая помогает понять жизнеспособность архитектуры. Для расчета возьмем данные из dashboard OpenRouter:
Обработка 6 изображений с помощью google/gemini-2.5-flash-image стоит около $0,25;
Анализ 6 нарядов с помощью google/gemini-2.5-flash стоит примерно $0,05;
Итого одна примерка из 6 изображений стоит $0,30 ( ~ 30 ₽).
Получается, что пять примерок требуют 150 ₽, а я продаю пакет из пяти примерок за 100 ₽.
Отличный бизнес: продаём за 100 ₽ то, что обходится в 150 ₽ :)
Если решить развивать PoC дальше, то для такого проекта возможны следующие каналы привлечения пользователей:
Органический трафик – пользователи, которые приходят без прямой платной рекламы, например, из поисковой выдачи Google и Яндекса.
Пользователи также могут приходить с Хабра, Telegram, YouTube, по ссылкам друзей и из других каналов. Это уже шире, чем классический органический трафик.
Все больше переходов начинают приносить AI-поисковики и чат-боты, которые показывают пользователям ссылки на внешние сайты.
Классическая контекстная реклама тоже никуда не девается.
Отдельное направление монетизации – сделать SaaS-решение для маркетплейсов или интернет-магазинов, где подобная технология может использоваться для виртуальной примерки и сравнения образов.
Но это уже совсем не инженерная история.
AI уже умеет хорошо писать код, но он не несет ответственность за то, чтобы система была безопасной, платеж не был начислен дважды, данные одного пользователя не увидел другой, а стоимость LLM не вышла из-под контроля.
Поэтому роль инженера не исчезает – она меняется [10]. Ценность инженера смещается от знания синтаксиса к способности видеть систему целиком, понимать API, границы доверия, обработку ошибок, структуру данных, стоимость и архитектурные компромиссы, а также обеспечивать надежность системы.
AI ускоряет написание системы. Инженер отвечает за то, чтобы получилась правильная система.
Автор: AlexeySushkov
Источник [11]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/35754
URLs in this post:
[1] MirrorVote: http://mirror-vote.ru
[2] ошибки: http://www.braintools.ru/article/4192
[3] MirrorVote : https://mirror-vote.ru/
[4] GitHub: https://github.com/AlexeySushkov/MirrorVote
[5] логика: http://www.braintools.ru/article/7640
[6] OWASP : https://owasp.org/
[7] безопасности API Security.: https://api-security.owasp.org/editions/2023/en/0x00-header/
[8] API3:2023 Broken Object Property Level Authorization: https://api-security.owasp.org/editions/2023/en/0xa3-broken-object-property-level-authorization
[9] Безопасность REST API от А до ПИ: https://habr.com/ru/articles/503284/
[10] она меняется: https://habr.com/ru/articles/1071400/
[11] Источник: https://habr.com/ru/articles/1082454/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1082454
Нажмите здесь для печати.