Создать SaaS с помощью ИИ сегодня реально: кодовый агент вроде Claude Code или Codex способен за несколько дней написать регистрацию, подписки, дашборд и API. Но для рабочего MVP мало просьбы «сделай мне SaaS». Нужны объём, урезанный до одного основного сценария, письменная спецификация, которую агент читает в каждой сессии, и тесты там, где живут деньги и изоляция данных. В этой статье я описываю процесс, которому следую сам: от определения объёма до деплоя.
Цель — руководство, по которому справится и тот, кто почти не пишет код или не пишет совсем. Выпустить прототип с помощью vibe coding легко; трудно поддерживать продукт живым, когда кто-то вводит данные банковской карты. Поэтому я буду отмечать, где можно двигаться быстро, а где стоит притормозить.
1. Сведите объём к одному основному сценарию
MVP редко гибнут из-за кода. Они гибнут из-за объёма. Агент напишет всё, что вы попросите; проблема в том, что каждую добавленную функцию нужно тестировать, поддерживать и отлаживать.
Прежде чем начинать, напишите одно предложение: «Пользователь делает ___ и получает ___». Например: «Агентство загружает посты клиента для соцсетей, а клиент согласовывает их по одной ссылке». Всё, что не вошло в это предложение, уходит во вторую версию.
Первой версии обычно хватает:
- регистрации, входа, сброса пароля;
- организации (тенанта) с приглашёнными участниками;
- одного основного сценария (предложение выше);
- одного платного тарифа с ежемесячной подпиской;
- простой страницы настроек и ссылки на портал оплаты.
Центр уведомлений, матрица ролей, несколько языков, мобильное приложение, админка: всё это позже. Если клиенты платят за основной сценарий, они сами скажут, что им ещё нужно.
2. Напишите спецификацию, которой следует агент
Между разговорами агенты не помнят ничего. Claude Code читает CLAUDE.md в корне проекта в каждой сессии; Codex и многие другие агенты читают AGENTS.md. Запишите решения туда, и каждая новая сессия будет начинаться с одних и тех же правил. Если вы пользуетесь обоими агентами, держите содержимое в одном файле, а в другом сделайте ссылку на него.
Полезная спецификация короткая и конкретная:
# Project: ApproveLink (MVP)
## Product
Agencies upload posts; the client approves or comments from one link.
## Stack
- Next.js (App Router, TypeScript), Tailwind
- Supabase: Postgres, Auth, Storage
- Stripe: one plan, monthly subscription, Checkout + Customer Portal
- Tests: Vitest (unit), Playwright (end to end)
## Rules
- Every table has organization_id; RLS is on for every table.
- Subscription status changes only from the Stripe webhook.
- Database changes only through migration files.
- Secrets live in .env.local; never in code or logs.
- Ask before adding a new package.
- After every task: pnpm lint && pnpm test
## Out of scope (for now)
Roles, i18n, mobile, admin panel.
Раздел «вне объёма» важен. Агенты стараются быть полезными и добавляют то, о чём вы не просили; письменная граница заметно сокращает такие вольности.
3. Выбор стека: берите скучное
Когда работаете с ИИ, лучший стек — тот, примеров которого агент видел больше всего. Для такого MVP я бы взял:
- Next.js + TypeScript: фронтенд и API в одном проекте. TypeScript ловит часть ошибок агента ещё на сборке.
- PostgreSQL (Supabase или другой управляемый Postgres): реляционные данные, row-level security (RLS) и миграции. Supabase заодно даёт аутентификацию и файловое хранилище в одном месте.
- Готовая аутентификация: Supabase Auth, Auth.js или Clerk. Не заставляйте агента писать хранение паролей и управление сессиями с нуля.
- Подписки Stripe: Checkout для страницы оплаты, Customer Portal для смены тарифа и отмены. Форму для ввода карты вам делать не придётся.
- Vercel или похожая платформа: деплой при каждом push и свой preview URL для каждой ветки.
Что установить: Node.js (LTS), pnpm, Git, аккаунт GitHub, Supabase CLI, Stripe CLI и кодового агента (claude или codex).
pnpm create next-app@latest approvelink --typescript --tailwind --app
cd approvelink
git init && git add -A && git commit -m "chore: empty project"
Положите спецификацию в корень этой папки и тоже закоммитьте её.
4. Первый промпт: сначала план, потом код
В первом сообщении я прошу не код, а план. Прочитать и поправить план намного дешевле, чем откатывать 40 неправильно написанных файлов.
Read CLAUDE.md. Don't write code yet.
Produce an implementation plan for this MVP:
1. Database tables (fields, relations, RLS policies)
2. Pages and API routes
3. The Stripe flow (which webhook events, where subscription status lives)
4. 6–8 small steps in order, each with what gets tested at the end
List anything unclear as questions at the end.
Прочитайте план, ответьте на вопросы, при необходимости обновите спецификацию. Затем пусть агент выполняет шаги по одному:
Implement step 1 of the plan: write the migration for the organizations,
memberships and projects tables and add the RLS policies. When done,
apply the migration to the local database, write a test proving two
different users can't see each other's data, and run it. Then stop.
«Then stop» здесь не случайно. После каждого шага я смотрю diff и делаю коммит, так что если агент собьётся с курса, есть чистая точка для возврата.
5. Изоляция данных тенантов: самое опасное место
Худшая ошибка SaaS звучит так: «Клиент A увидел данные клиента B». Код агента обычно выглядит нормально, потому что при разработке вы тестируете его одним пользователем. Проблема проявляется, когда приходит второй клиент.
Мои правила:
organization_idв каждой таблице. Без исключений, включая дочерние таблицы.- Пусть фильтр обеспечивает база данных. В Supabase/Postgres включите RLS для каждой таблицы и напишите политику вокруг организаций, к которым принадлежит пользователь. Одного
where organization_id = ...в коде приложения недостаточно: агент может забыть его в следующем запросе. - Ключ service role остаётся на сервере. Он обходит RLS. Он не должен попадать в код, который уходит в браузер; в Next.js никогда не кладите его в переменную
NEXT_PUBLIC_. - Тестируйте двумя пользователями. Создайте две организации и, войдя под одной, попробуйте получить запись другой по её ID. Этот тест должен быть автоматическим и запускаться при каждом изменении.
Спросите агента напрямую: «Перечисли все места в этом проекте, которые обходят RLS». В ответе должен быть серверный код с service role и webhook; если там что-то ещё, спросите, зачем.
6. Миграции: никогда не меняйте базу вручную
Когда агенту нужно добавить столбец, он должен сделать это через файл миграции, а не кликами в дашборде. С Supabase CLI это выглядит так:
supabase start # local Postgres (needs Docker)
supabase migration new add_projects # empty migration file
supabase db reset # apply all migrations from scratch
supabase db push # apply to the remote database
Регулярно запускайте db reset: если миграции не применяются чисто с нуля, у продакшена тоже будут проблемы. После запуска читайте каждую миграцию, которую пишет агент. Если видите DROP COLUMN, DROP TABLE, UPDATE без WHERE или блокирующий индекс на большой таблице, остановитесь и спросите, зачем. Миграцию, удалившую данные, не отменить.
7. Тестируйте пути денег
Тесты на всё не нужны; время MVP коротко. Но эти пути не должны попадать в продакшен без тестов:
- Регистрация → создание организации → основной сценарий. Сквозной тест на Playwright.
- Webhook Stripe. Правильно ли обновляется статус подписки при
checkout.session.completed,customer.subscription.updated,customer.subscription.deletedиinvoice.payment_failed? - Доступ без оплаты. Когда подписка отменена или платёж не прошёл, платная функция действительно закрывается?
- Изоляция данных. Тест с двумя пользователями, описанный выше.
Webhook Stripe можно проверить локально так:
stripe login
stripe listen --forward-to localhost:3000/api/webhooks/stripe
stripe trigger checkout.session.completed
Промпт для агента:
Review the Stripe webhook route. Is the signature verified? What happens
if the same event arrives twice (idempotency)? Which table holds
subscription status? Write tests for these four events:
checkout.session.completed, customer.subscription.updated,
customer.subscription.deleted, invoice.payment_failed.
Run them and show me the result.
Частая ошибка: агент активирует подписку на странице «успех», на которую Stripe делает редирект. Этот URL может открыть вручную кто угодно. Статус должен меняться только из webhook с проверенной подписью.
8. Деплой и мониторинг
На платформе вроде Vercel всё просто: отправьте репозиторий на GitHub, подключите проект, введите переменные окружения в дашборде. У каждого pull request свой preview URL; проверяйте изменения там, до продакшена.
Мой чек-лист перед запуском:
- переменные окружения заданы в продакшене; живые и тестовые ключи Stripe не перепутаны;
- в Stripe настроен боевой endpoint для webhook, его секрет подписи лежит в переменной окружения;
- миграции применены к продакшен-базе;
- redirect URL для Supabase Auth заданы для продакшен-домена;
- резервные копии базы включены.
Для мониторинга добавьте сервис отслеживания ошибок вроде Sentry, чтобы видеть ошибки раньше, чем пользователь напишет «всё сломалось». Агенту достаточно сказать: «Add Sentry to the Next.js project, capture server and client errors, and don’t attach user emails or secret values to events». Добавьте и простую проверку доступности (uptime).
В чём ошибается ИИ
- Выдумывает несуществующие API. Особенно в новых версиях библиотек. Если сборка или тесты падают, передайте ошибку агенту как есть и попросите свериться с официальной документацией.
- Правит тест, чтобы он проходил. Если в diff появился файл теста, спросите, зачем.
- Добавляет ненужные пакеты. Правило «спрашивай перед добавлением пакета» из спецификации здесь окупается.
- Проглатывает ошибки. Пустые блоки
catch {}делают сбои платежей невидимыми. - Авторизация на клиенте. Скрытая кнопка — не безопасность; проверка должна быть на сервере и в базе.
- Расширяет объём. Откатывайте функции, которые приходят с «я ещё добавил…», или переносите их в отдельную ветку.
- Теряет контекст в длинных сессиях. По мере роста разговора агент забывает ранние решения. Начинайте новую сессию на каждый шаг; долгоживущие решения уже лежат в спецификации. Закрыть сессию до того, как заполнится контекстное окно, полезно и для качества, и для расхода токенов.
Безопасность: коротко, но серьёзно
- Секреты хранятся в
.env.local. Проверьте, что файл есть в.gitignore. Если ключ хоть раз попал в коммит, отзовите его и выпустите новый; удалить его из истории недостаточно. - Никогда не вставляйте API-ключи в чат. Агенту не нужно видеть ключ, только имя переменной.
- Читайте команды, которые запускает агент. Особенно
rm,git push --force, команды для базы данных иcurl … | sh. Автоматически одобряйте только безопасное: чтение файлов и запуск тестов. - Не направляйте агента на продакшен-базу. Пусть работает с локальной или тестовой базой.
- Проверяйте ввод на сервере. Пусть каждый вход API валидируется библиотекой схем вроде Zod.
- Проверяйте зависимости. Время от времени передавайте агенту вывод
pnpm audit.
Когда подключить живого разработчика
Если вы столкнулись с чем-то из этого, несколько часов ревью у опытного разработчика того стоят:
- перед первым настоящим платежом (webhook, статус подписки, возвраты);
- когда данные клиентов включают персональные данные (GDPR и подобные обязательства);
- когда крупный клиент присылает анкету по безопасности;
- когда вы с агентом не можете исправить одну и ту же ошибку три сессии подряд;
- когда начинаются проблемы с производительностью (медленные запросы, отсутствующие индексы).
Держите наготове спецификацию, папку миграций и вывод тестов, чтобы ревью прошло быстро. Проект, написанный с агентом, но закоммиченный небольшими шагами и покрытый тестами, разработчик поймёт быстро.
Как я делаю это в AgentVera
Всё описанное выше работает и в одном терминале. Я использую AgentVera, чтобы управлять сразу несколькими агентами; вот что в нём помогает:
- Фронтенд и бэкенд в отдельных worktree. В рабочем пространстве я открываю агента Claude Code для API и webhook и агента Codex для UI, каждого в своём git worktree. Они не трогают одни и те же файлы и потому не ломают друг друга. Метод описан в статье git worktree для параллельных агентов.
- Diff перед слиянием. Панель Git показывает изменения каждого worktree, а code review проверяет каждый завершённый ход. На что смотреть, написано в статье ревью кода от ИИ.
- Просмотр базы данных. В менеджере баз данных я открываю таблицы локального Postgres и проверяю, что агент реально написал; DB Guard помечает рискованные миграции в конце хода.
- Превью. Окружения предпросмотра дают dev-серверу каждого worktree свой адрес, так что я могу сравнивать две ветки бок о бок.
- Слежение за токенами. В каждой панели виден размер контекста в реальном времени; когда он раздувается, я закрываю сессию и начинаю заново.
Это ускоряет работу, но не заменяет правила выше: спецификация, тесты и ваша собственная проверка по-прежнему важны.
Итоги
Создание SaaS с помощью ИИ — это не столько генерация кода, сколько запись решений и защита критичных путей. Сведите объём к одному сценарию, запишите решения в CLAUDE.md или AGENTS.md, выберите скучный, популярный стек, обеспечьте изоляцию тенантов в базе, протестируйте пути денег и настройте мониторинг до деплоя. Пусть человек посмотрит проект до того, как появятся реальные деньги и реальные данные. Если хотите запускать агентов параллельно, скачайте AgentVera бесплатно и откройте свои первые два worktree.