Перейти к содержанию
Публикация AiManual

AI пишет код, но не архитектуру: чему учит пет-проект MirrorVote на Supabase и OpenRouter

Пет-проект MirrorVote: код написал Claude Code, а архитектуру, RLS, идемпотентные webhook ЮKassa, retry для LLM и observability пришлось делать вручную. Разбира

Коротко

Что будет в материале

  1. 01

    Что такое MirrorVote и почему это показательный кейс

  2. 02

    Стек MirrorVote: Supabase Edge Functions, OpenRouter и обвязка на VPS

  3. 03

    Что AI не закрывает: инженерные задачи, которые пришлось решать вручную

  4. 04

    Экономика сценария: сколько стоит одна примерка в MirrorVote

MirrorVote - пет-проект, в котором весь код приложения написан нейросетью в Claude Code, а архитектуру, деплой и эксплуатацию делал человек. Это честная иллюстрация рабочего процесса 2026 года: AI ускоряет набор кода, но проектирование системы, границы доверия и архитектурные компромиссы остаются за инженером. Код быстро генерируется, а решения о безопасности, платежах и стоимости ошибок по-прежнему принимает человек.

Где проходит эта граница, видно на конкретных задачах. AI уверенно пишет обработчики, CRUD и вызовы API. Он не решает, как ограничить доступ к чужим строкам в базе, как не списать деньги дважды при повторном webhook и как не уйти в минус по стоимости вызовов LLM. Главный тезис простой: роль инженера смещается от написания кода к проектированию системы, и MirrorVote на Supabase и OpenRouter показывает это лучше многих теоретических статей.

Если коротко, MirrorVote - это AI-помощник выбора образа. Пользователь загружает несколько фотографий, система приводит их к единому виду (фон, свет, поза) и оценивает наряды с учётом повода. Дальше можно собрать мнение друзей по публичной ссылке. За простой обёрткой стоит полноценный набор интеграций: авторизация, хранение файлов, платежи и несколько вызовов LLM на один запрос.

Что такое MirrorVote и почему это показательный кейс

Проект ценен тем, как он собирался, а не набором функций. Код писался через вайбкодинг в Claude Code, исходники лежат в Git. Всё, что касается архитектуры, развёртывания и эксплуатации, тянул на себе человек. Такое разделение труда - не случайность, а следствие природы AI-инструментов: они отлично работают внутри понятной задачи и теряются на стыках между сервисами.

Пользовательский сценарий MirrorVote в двух словах

Один запрос на примерку запускает цепочку шагов. По разбору проекта последовательность выглядит так:

  1. Авторизация через Google OAuth, на выходе - JWT-токен для последующих запросов.
  2. Загрузка фотографий для анализа.
  3. Проверка пользователя и доступного лимита в PostgreSQL.
  4. Вызов LLM: обработка фотографий, анализ образов, формирование рекомендаций.
  5. Сохранение обработанных изображений в Storage, результатов анализа и оценок в PostgreSQL, списание лимита.
  6. Возврат пользователю обработанных изображений и результата анализа.

Отдельная ветка сценария - публичная ссылка для голосования: пользователь генерирует её и делится с друзьями. Простая функция на первый взгляд, но она открывает доступ к данным и требует аккуратной настройки прав.

Почему PoC - это не продакшен, и какие упрощения допустимы

Для PoC не нужна промышленная надёжность, и это позволяет урезать каждый этап классического цикла разработки. В материалах по проекту перечислены те самые упрощения. Анализ требований сводится к минимальному пользовательскому сценарию или MVP. Проектирование ограничивается минимальной схемой БД и только критичными интеграциями: Auth, LLM, платежи. Код пишется через вайбкодинг и хранится в GitHub. Тестирование - ручные проверки основных сценариев. Развёртывание - локально или на облачном VPS, вручную либо через GitHub Actions. Эксплуатация - базовая observability: ошибки в логах, доступность приложения, стоимость внешних сервисов.

Упрощения не отменяют архитектурных решений. Они лишь снижают планку по нагрузке и надёжности. Границы доступа, идемпотентность платежей и обработку сбоев LLM всё равно нужно продумать, иначе PoC съест деньги или данные раньше, чем дойдёт до пользователей.

Стек MirrorVote: Supabase Edge Functions, OpenRouter и обвязка на VPS

Стек у проекта типовой для небольших AI-сервисов. Supabase закрывает базу, файлы и серверную логику, OpenRouter даёт доступ к моделям, а VPS с Nginx образует внешний контур. Разберём, зачем нужен каждый компонент и где он начинает требовать ручной работы.

КомпонентРоль в системе
Supabase Edge Functions на DenoСерверная логика без отдельного бэкенда
PostgreSQLПользователи, лимиты, результаты анализа и оценки
StorageХранение обработанных изображений
Nginx на VPSReverse proxy, TLS, маршрутизация запросов
Google OAuthАвторизация и выдача JWT
ЮKassaПриём платежей
OpenRouter (Gemini 2.5 Flash, Gemini 2.5 Flash Image)Обработка и анализ изображений

Почему Supabase Edge Functions на Deno

Edge Functions позволяют держать серверный код рядом с базой и хранилищем, без отдельного бэкенда и своего деплоя. Среда выполнения - Deno. Для пет-проекта это экономит время: не нужно поднимать сервер, настраивать окружение и CI для бэкенда. Логика обработки изображений и вызовов LLM живёт рядом с данными.

У подхода есть границы. Функции на Edge чувствительны к холодным стартам, у них ограничено время выполнения, а секреты вроде ключей OpenRouter нужно хранить аккуратно и не тянуть в клиент. Тяжёлые задачи, например обработку шести изображений за раз, стоит проверять по длительности, чтобы не упираться в лимиты платформы.

Зачем Nginx на VPS, если есть Supabase

Supabase даёт API и хостинг функций, но внешний вход в приложение удобно держать на своём домене. Nginx на VPS работает reverse proxy: принимает запросы из интернета, терминирует TLS, раскидывает трафик по нужным сервисам. Это даёт контроль над доменом, заголовками и базовой защитой, а ещё позволяет прятать внутренние адреса за одним входом.

За предсказуемость приходится платить ручной работой: конфиг Nginx, обновление сертификатов, слежение за состоянием сервисов. Для PoC это терпимо, в продакшене такой слой требует автоматизации.

Выбор Supabase снижает объём инфраструктурного кода, но переносит часть ответственности на настройку RLS и политик доступа. Здесь начинается зона, где AI помогает, но не берёт решения на себя.

Что AI не закрывает: инженерные задачи, которые пришлось решать вручную

Публичный разбор проекта не приводит конкретных SQL-политик и кода обработчиков, поэтому дальше - принципы, которые применяют в таком стеке и которые AI не выводит сам. Он не знает бизнес-контекст, не взвешивает архитектурные компромиссы и не несёт ответственности за безопасность и деньги.

RLS и защита публичных ссылок в Supabase

RLS (Row Level Security) в PostgreSQL ограничивает доступ на уровне строк. В MirrorVote это критично: пользователь видит только свои данные, а публичная ссылка для голосования открывает лишь нужные изображения и ничего лишнего. Без RLS любой запрос к таблице через API может вернуть чужие записи, потому что Supabase отдаёт доступ к таблицам напрямую.

Подход строится на политиках, привязанных к JWT: политика проверяет идентификатор пользователя и роль, а доступ к Storage ограничивается отдельно от таблиц. AI может сгенерировать каркас политики, но проверить границы доступа и продумать сценарии атаки должен инженер. Публичная ссылка - самый рискованный элемент: её легко сделать слишком широкой и открыть доступ к лишним фотографиям.

Идемпотентная обработка платёжных webhook ЮKassa

Платёжные сервисы повторяют webhook при сбоях сети или таймаутах. Если обрабатывать каждое уведомление как новое, пользователю спишут лимит дважды, а в базе появятся дубли. Идемпотентность решает это через уникальный идентификатор события и проверку, обрабатывалось ли оно раньше. На практике это таблица обработанных событий, транзакции и проверка статуса перед изменением баланса.

AI напишет код обработчика, но не выберет стратегию: где хранить ключи идемпотентности, что делать с частично выполненным платежом, как вести себя при расхождении статусов. Это архитектурное решение, и оно напрямую влияет на деньги.

Retry при ошибках LLM API через OpenRouter

Вызовы LLM через OpenRouter могут падать: таймауты, лимиты, недоступность модели. Без повторов пользователь теряет запрос, а с неаккуратными повторами оплачивает одну примерку несколько раз. Нужен retry с экспоненциальной задержкой и ограничением числа попыток, при этом списание лимита не должно дублироваться.

Retry - это часть архитектуры, а не цикл в коде. Приходится решать, где хранить состояние между попытками, как уведомлять пользователя о задержке, что логировать. AI предложит шаблон, но границы и стратегию выбирает инженер.

Observability и контроль стоимости вызовов

Базовый набор для PoC: логи ошибок, контроль доступности приложения, учёт стоимости внешних сервисов. В MirrorVote важно считать вызовы LLM через OpenRouter и платежи. Простые приёмы - логировать каждый вызов с моделью и объёмом токенов, держать дашборд по расходам и ставить алерт при превышении порога. AI сам это не настроит: нужен инженерный взгляд на метрики и пороги, а также понимание, какие отклонения считать авариями.

Экономика сценария: сколько стоит одна примерка в MirrorVote

По оценке, приведённой в описании кейса, обработка и анализ шести изображений через Gemini 2.5 Flash и Gemini 2.5 Flash Image обходятся примерно в $0,30 за примерку. Это ориентир для PoC, а не гарантированный тариф: стоимость зависит от модели, размера изображений и текущих цен провайдера.

Как считать стоимость LLM-вызовов на пользователя

Формула простая: число вызовов умножить на среднюю стоимость вызова. Обработка изображений и анализ образов - разные вызовы с разной ценой, поэтому их считают отдельно. На примере MirrorVote шесть изображений проходят через обработку, затем модель анализирует наряды, и суммарно выходит около $0,30. Для пет-проекта это приемлемо, при росте пользователей нужны лимиты и регулярный контроль расходов.

Выбор модели сильно меняет цифру. Если сравнивать провайдеров и версии, разница в стоимости может быть кратной, и это отдельная задача - подобрать модель под бюджет и качество. Такие компромиссы между архитектурой LLM, контекстным окном и стоимостью инференса разобраны в материале про выбор LLM и стоимость инференса.

Где заканчивается PoC и начинается продакшен-экономика

PoC может позволить себе ручные проверки и отказ гнаться за производительностью. Продакшен приносит требования к SLA, масштабированию и снижению стоимости. Решения, принятые на старте, становятся узким местом: без кэширования одинаковые примерки оплачиваются заново, а без батчинга вызовы дорожают. Критерии перехода понятны: растёт число пользователей, растёт счёт за LLM, появляются требования к надёжности. Тогда стоит пересматривать архитектуру и экономику сценария, а не ждать, пока расходы выйдут из-под контроля.

Чему учит MirrorVote: роль инженера смещается, а не исчезает

AI ускоряет написание кода, но архитектура, безопасность, платежи и эксплуатация остаются за инженером. Роль смещается от набора строк к проектированию системы, границам доверия и компромиссам. MirrorVote даёт готовый список участков, где нужен человек: RLS и публичные ссылки, идемпотентность webhook, retry для LLM, observability, контроль стоимости.

Выводы о том, что программисты больше не нужны, пока опережают данные. Бенчмарки вроде Real-SWE как раз пытаются измерить AI на реальных задачах разработки, и их результаты стоит читать с оговорками, ведь методология и набор задач у таких тестов ограничены (см. разбор Real-SWE и слухов о смерти программистов).

Как использовать CLAUDE.md для постоянного контекста

Claude Code поддерживает файловую систему памяти через CLAUDE.md. Память даёт постоянный контекст между сессиями: стандарты проекта, личные предпочтения разработки, правила для конкретных директорий, а также версионирование вместе с проектом. Это описано в руководстве по памяти Claude Code.

Практическая польза для такого PoC - зафиксировать в CLAUDE.md требования к RLS, идемпотентности и retry, чтобы AI учитывал их при генерации кода. Это снижает число ошибок, но не заменяет архитектурное мышление: правила пишет инженер, а модель лишь следует им.

Когда вайбкодинг оправдан, а когда нет

Вайбкодинг разумен для PoC и MVP, где важна скорость и допустимы упрощения. Для продакшена с платежами, персональными данными и высокими требованиями к надёжности одного AI мало: нужен дополнительный инженерный контроль. Риски известны: дырявые политики RLS, двойные списания, потеря данных при сбоях LLM. AI не несёт ответственности за результат, поэтому проверка и проектирование остаются на человеке.

Инструменты для AI-разработки быстро развиваются, и их полезно оценивать по методологии, а не по хайпу. Как это делают на практике, включая сравнение обвязок для кодинг-агентов по стоимости и качеству, показывает разбор оценки агентов от Databricks.

Практический вывод для своих проектов: используйте вайбкодинг для MVP, но с первого дня закладывайте решения по безопасности и деньгам - RLS, идемпотентность, retry, лимиты. Заведите CLAUDE.md с правилами проекта, держите код в Git, планируйте observability сразу, а не после первого инцидента. Подход работает не только для MirrorVote, но и для других AI-пет-проектов на Supabase и OpenRouter.

Подписаться на канал