Пятого апреля 2026 года я начал проверять гипотезу: можно ли собрать работающий MVP SaaS за месяц на подписке Cursor за $20, работая по три-четыре часа четыре вечера в неделю. Через месяц MVP был. Второго сентября я выкатил релиз 2026.09.2, а между этими датами уместились больше 500 коммитов, 61 фаза разработки и семь модулей в проде.
По порядку: почему пришлось собирать свой инструмент, как устроен стек, как разделение работы между моделями дало такую скорость и что из задуманного не сработало.
Оговорюсь сразу о двух вещах. RetroPoint делаю я, так что читайте это как рассказ заинтересованного лица. И разработчик тут действительно один, но не с чистого листа.
Дизайн RetroPoint я заказал у дизайнера Натальи 10 декабря 2022 года. Она проработала только модуль ретроспектив, но этого хватило, чтобы задать визуальный язык продукта. До полноценной разработки постоянно не доходили руки. Я вернулся к отложенной идее весной 2026-го, когда развитие AI-моделей и агентов сделало такой запуск в одиночку реалистичным. С помощью Claude Design и современных AI-моделей я продолжил исходную систему уже без дальнейшего участия дизайнера и перенес ее на остальные модули.
Почему пришлось собирать свое
Я в разработке семнадцатый год, двенадцать из них руковожу командами разного размера и зрелости. Для ретроспектив, оценки задач, целей и встреч один на один находился свой инструмент, но вместе они не складывались в единый рабочий ритм. Контекст был разнесен по сервисам, таблицам, календарям, чатам и личным заметкам, а связывать его приходилось вручную.
Потом привычный набор рабочих сервисов стал менее предсказуемым.
Менялись условия оплаты и доступа, а вместе с ними появлялся риск потерять накопленную историю встреч. Я не хотел снова строить процесс команды вокруг инструментов, доступность которых не контролирую.
Российские сервисы никуда не делись и работают. Когда я выбирал замену как тимлид, доступные мне продукты хорошо закрывали отдельные процессы, но не связывали их результаты в единый рабочий цикл.
Чего мне не хватало
Хорошая ретроспектива заканчивается договоренностями. Ради них встречу и собирали. Но после фиксации решений работа в инструментах обычно заканчивалась.
В командах, которыми я руководил, процесс чаще всего ломался в трех местах:
- Контекст распадается. Цели живут в таблице, встречи в календаре, договоренности в чате, а личные заметки руководителя отдельно от всего этого.
- Договоренность теряется. Записать решение мало. Нужно понимать, к какой цели оно ведет, кто отвечает, насколько это важно и к какому сроку.
- Тимлид сшивает воркфлоу руками. Перед каждой встречей он заново собирает факты и переносит следующие шаги между сервисами.
Мне нужна была не доска, а связка «встреча, решение, действие с ответственным и сроком», чтобы следующий цикл начинался с того, чем закончился прошлый.
Что получилось
Сейчас в проде семь самостоятельных модулей: ретроспективы с 19 готовыми техниками, Planning Poker, OKR, встречи 1‑2‑1, Performance Review, рабочие встречи и календарь отсутствий с днями рождения.
Что я сделал и о чем не жалею:
- Модули подключаются по одному. Неподключенный модуль не появляется в меню, поэтому рабочее место не зарастает кнопками, которыми никто не пользуется.
- Участник заходит на публичную доску по ссылке без регистрации и без обязательного имени. Аккаунт нужен только организатору.
- Договоренность превращается в действие с ответственным, сроком и ссылкой на исходную встречу.
- AI-помощник собирает темы, готовит итоги и предлагает следующие шаги, но ничего не применяет без подтверждения человека.
- Данные хранятся в России, оплата идет в рублях, а 27 июля продукт включили в реестр операторов персональных данных. Для части российских команд это входное требование к новому сервису.
Как это устроено
Бэкенд работает на Python 3.12 и FastAPI, данные лежат в PostgreSQL 16 через SQLAlchemy 2.0 и Alembic. Слои обычные: api, service, repository и adapters. Доска обновляется у всех участников через SSE, PDF собирается reportlab, файлы уходят в S3-совместимое хранилище.
На фронтенде React 18 с TypeScript и сборка на Vite. Перетаскивание карточек на dnd-kit, текстовые поля на TipTap, графики на ECharts. Инфраструктура простая: Docker Compose, GitLab CI, VDS на Ubuntu и nginx.
Дольше всего я возился с SEO у SPA. Публичная часть сайта живет на том же React-роутере, и по умолчанию поисковый робот получает пустой <div id="root">. Решение немодное, но работает. На сборке я собираю второй, серверный бандл через vite build --ssr, прогоняю по нему все публичные маршруты и раскладываю готовый HTML рядом со статикой. Оттуда же генерируется sitemap.xml из тех же данных, что и сами страницы, поэтому карта сайта не расходится с реальностью. Сборка падает, если у страницы пустой <title>, отсутствует description или подозрительно мало HTML внутри #root.
В public лежит еще один файл, llms.txt. В нем карта публичной части сайта с явными границами для AI-агентов: где смотреть актуальные тарифы и почему этот файл не служит API. Мне важно, чтобы бот, которого спросили про сервисы ретроспектив, читал текущие условия, а не пересказ статьи двухлетней давности. Проверять такой файл глазами бессмысленно, поэтому у него есть контрактный тест. Меняются тарифы или состав модулей в коде, а llms.txt не обновлен, и тест краснеет.
Как один человек тянет 61 фазу
Такой объем в одиночку я бы не вытянул без AI-агентов, но подход «просто попросить написать код» не работает вообще.
В моей схеме сильная модель принимает решения, а более доступная их исполняет. Claude Opus внутри Cursor снимал неопределенность: выбирал продуктовое и архитектурное решение, а потом превращал его в подробное ТЗ с критериями готовности. Реализацию по готовому контракту забирали более доступные модели. Главная экономия была не в стоимости запросов, а в том, что решение принималось один раз. Более доступные модели получали готовое ТЗ и не тратили время на повторный выбор подхода.
Когда ТЗ можно отдавать исполнителю. Да-да, по ходу работы я изобрел свой велосипед — локальную версию Spec-Driven Development. Superpowers, Spec Kit и OpenSpec я не использовал. Вместо готового фреймворка постепенно собрал процесс вокруг проектных спецификаций в файлах docs/plan/phase-NN-*.md, которые появляются до кода. Передавать план можно, когда в нем приняты все ключевые решения. Исполнителю не нужно угадывать, зачем нужен сценарий и кто им пользуется, что входит в scope и что намеренно исключено, какой существующий паттерн продолжать, какие роли, права, тарифы и состояния учитывать, как выглядит API-контракт и чем доказывать готовность. Если хоть по одному пункту осталась развилка, исполнитель тихо начинает работать архитектором, и дешевая реализация превращается в дорогую переделку. Половина ошибок отсекается прямо здесь, потому что противоречие видно в тексте, а не в диффе на 900 строк.
Дизайн-токены сделали визуальное ТЗ достаточно точным. Исходный дизайн покрывал только ретро, но уже задавал палитру и типографику продукта. Все остальные модули, от Planning Poker до Performance Review, я проектировал в Claude Design поверх этой системы. Помог не запрос «нарисуй красиво». Помогло то, что у агента были docs/design-tokens.md и tokens.css: семантические роли цвета, шкала типографики, 8pt-сетка, радиусы и размеры контролов. Макет показывает одно правильное решение. Дизайн-токены объясняют агенту, почему это решение принадлежит именно этому продукту. Иерархию, плотность, состояния и права по-прежнему принимал я.
Где схема ломалась. На сквозном фронтенде несколько попыток Claude Sonnet и Composer 2.5 не прошли мою приемку. Дело было не в моделях. Под видом реализации я отдавал им еще не законченное проектирование. Это хорошо показывает Planning Poker: коммит 9e5ba4c затронул 42 файла и добавил 4839 строк, а полный прогон включал 323 теста. Сложность там создает не объем JSX. Экран одновременно держит состояние сессии, роли участников, ограничения тарифа и визуальную иерархию. Opus снял развилки, и после этого части снова уходили исполнителям.
Проектные скиллы в репозитории. Для RetroPoint я сделал отдельные скиллы и храню их рядом с кодом. Это не универсальные инструкции для любого репозитория, а накопленный контекст конкретного продукта. В них зафиксированы карта UI-примитивов, правила слоев бэкенда, подход к архитектурным планам, редакционный стиль и требования внешних площадок. Поэтому агент точнее понимает существующие решения, а договоренности не теряются между чатами.
Скучные правила репозитория. Ни npm, ни python с хоста, все команды идут в контейнерах api и frontend из корневого compose. Скучно, зато «у меня работает» больше не случается. Второе правило с первого дня: агент не коммитит без явной команды и не решает сам, что работа закончена.
Контрактные тесты на публичные обещания. Критичные обещания на сайте проверяются кодом. Один тест сверяет цифры на странице тарифов с лимитами в бэкенде. Другой держит llms.txt. Третий проверяет SEO-метаданные на сборке фронта. Агент может уверенно написать «до 10 активных досок», и остановит его только красный тест.
Что не сработало
Теперь про грабли.
Страница тарифов. Я собрал четыре тарифа и шестнадцать дополнительных пакетов с отдельной таблицей возможностей для каждого. Вышла страница высотой около 28 500 пикселей с восемью таблицами. Мне казалось, что так честнее: человек видит все и выбирает точно. На деле выбор такой сложности человек не делает, он закрывает вкладку. В 55-й фазе я переупаковал все заново и свел линейку к постоянному бесплатному тарифу, двум платным вариантам для одной команды и небольшого направления, а также корпоративному тарифу по запросу. При регистрации по-прежнему доступны 30 дней полного продукта без карты и автосписания.
Приватная фича, из-за которой сайт пропал из выдачи всех поисковиков. Одиннадцатого апреля я поднял pre-render всех публичных маршрутов и успокоился. Двадцать первого мая, занимаясь совсем другой задачей про восстановление сессии в новой вкладке, я поставил AuthSessionProvider, который возвращал null, пока не проверит cookie. В статике все лежало правильно. Но React гидратировался, вычищал #root и держал его пустым до ответа бэкенда, так что краулер с JS получал пустую страницу на каждом публичном маршруте. Так продолжалось неделю, и этого хватило, чтобы поисковики убрали RetroPoint из выдачи. Сборка все это время была зеленой, потому что SEO-ассершены проверяли файл на диске, а не то, что остается после гидратации. Починил двадцать восьмого мая, вторым заходом второго июня добил клиентский рендер, а правильный вывод сделал только в конце июля, когда добавил post-deploy smoke по опубликованным адресам.
Страница регистрации отдавала 404. Пре-рендер знает только публичные маршруты, а все остальное в nginx уходило в error_page 404. Внешне все выглядело прилично: приложение поднималось и рисовало нужный экран. Но код ответа был 404, и в первом кадре успевала мигнуть надпись «Страница не найдена». Живой человек этого почти не замечал, а вот рекламный кабинет отклонял /register как посадочную страницу, и краулеры превью показывали в мессенджерах ошибку вместо карточки ссылки. Лечится SPA-фолбэком для приложенческих префиксов, при котором на все прочие адреса остается честный 404. Чувствительные файлы и раньше не попадали в публичную статику: .env исключался из сборочного контекста, секреты бэкенда хранились отдельно, а деплой публиковал только собранный фронтенд. В nginx я добавил еще один рубеж защиты. Теперь скрытые файлы и карты исходников возвращают 404, даже если однажды случайно окажутся в релизе. На эту мысль навели логи: сканеры регулярно пытались достать /app/.env. Конфиг уехал на прод первого сентября, за день до того, как я сел писать этот текст.
Один провайдер входа оказался точкой отказа. По срезу на второе сентября у 67 владельцев аккаунтов из 101 вообще не было локального пароля: они входили только через внешнего провайдера. До отключения Google был самым популярным внешним способом входа. Поэтому в июле исчезла не просто одна из кнопок, а привычный путь в продукт для заметной части аудитории. Часть 10 статьи 8 закона № 149-ФЗ ограничивает способы авторизации пользователей в России для российских владельцев сайтов и приложений. С 7 июля 2026 года закон № 199-ФЗ ввел за нарушение административную ответственность.
Яндекс уже был подключен, но закрывал только часть потребности. Неожиданным для меня оказалось другое: заметная часть регистраций через него пришла с корпоративных доменов. Корпоративные решения Яндекса привели в RetroPoint аудиторию, которую я не ожидал увидеть в этом канале.
После отключения Google я стал искать российский способ входа, который с высокой вероятностью уже есть у целевой аудитории. Выбор пал на Сбер ID и быстро себя оправдал. В срезе на четвертое сентября у Сбер ID было семь регистраций, у Яндекса 36, у отключенного Google 25, а у VK ни одной. Сбер ID появился в продукте только шестого августа, поэтому семь регистраций меньше чем за месяц стали для меня заметным сигналом спроса.
Теперь я отношусь к провайдеру входа как к неотъемлемой части доступа, а не как к еще одной кнопке. Зависимость от одного популярного способа авторизации становится продуктовым риском. Альтернативу лучше добавлять, пока основной канал еще работает.
Заодно выяснилось, что OAuth совсем не сводится к кнопке в форме. Нужно учесть callback, state и PKCE, привязку при занятом email, восстановление доступа, флаг функции, ошибки конкретного провайдера и отдельную приемку в рабочей среде.
Семь модулей, но ни один пока не стал привычкой. Срез рабочей среды на второе сентября: 101 активный владелец аккаунта, 97 из них сейчас внутри 30-дневного триала. Ретро-доски с карточками есть у 38 человек, всего 43 доски и 757 карточек. Дальше цифры падают: 7 команд, 20 встреч 1‑2‑1, 22 задачи в двух сессиях Planning Poker, один цикл Performance Review и ни одного цикла OKR. Вторую содержательную доску завели трое. С деньгами так же: одна оплата от внешнего пользователя за все время, 200 ₽ 12 мая. Вывод получился неприятный. Скорость разработки не равна скорости изменения привычек, и семь процессов я построил заметно раньше, чем у людей появился признак повторения хотя бы одного. Пять месяцев я занимался тем, что умею, архитектурой и модулями, и почти не занимался ни дистрибуцией, ни тем, чтобы довести до второй ретроспективы тех, кто уже пришел. С этой статьи и начинаю исправлять.
Что дальше
Дальше по плану аналитика воронки и UTM-атрибуция, а следом работа с дистрибуцией вместо очередного модуля.
Посмотреть, что получилось, можно на retropoint.ru. Бесплатный тариф с ретро-досками остается бесплатным.
Если вы тоже запускали продукт в одиночку, расскажите, как вы поняли, что пора отложить новые функции и заняться привлечением пользователей и продажами. Я слишком долго оценивал прогресс по темпу разработки. Коммитов и модулей становилось больше, но повторных пользователей и оплат почти не прибавлялось.

Top comments (0)