Ктоя и почему вообще взялся за код
18 лет я служил в армии и ушёл на пенсию с высокой должности. С 2019 года занимаюсь бизнесом — открыл больше 10 направлений. В IT и программировании опыта у меня не было.
Вайбкодингом я занялся плотно всего четыре месяца назад. Учился, ошибался, пробовал — и сразу на реальных проектах, а не на учебных демках. Дисциплина и привычка разбирать процесс по шагам остались с прежней работы, и они пригодились здесь больше, чем я ожидал.
Первые недели результата почти не было. Я кидал нейросети расплывчатые запросы, она генерировала что‑то, оно ломалось, я просил починить — ломалось другое. Токены уходили тоннами. Перелом случился, когда я перестал смотреть на это как на «накодить по приколу» и начал относиться как к проектированию.
Главное, что я понял: 80% результата это спецификация
Сдвиг в голове простой: код это не 80% работы, а 20%. Остальное — документ, который я пишу до того, как нейросеть что‑то соберёт.
Сначала я сажусь и расписываю продукт целиком. Не «человек ищет событие», а по шагам: открыл приложение, выбрал город, нажал «фильтры», выбрал «эти выходные» и «бесплатное», увидел счётчик «найдено 7 событий», тапнул на карточку. К каждому сценарию — критерии приёмки и ветки ошибок: что показать, если пропала сеть, если результатов ноль, если сервер отдал ошибку.
В спецификации EventMap расписаны:
-
сценарии пользователей — по шагам, с критериями приёмки на каждый;
-
модель данных — какие таблицы, какие связи, кто что имеет право видеть и менять;
-
бизнес‑логика — например, что цену размещения нельзя подделать с фронта, она зашита на сервере;
-
крайние случаи — отдельный блок, который я считаю самым важным. Что делать, если интернет пропал на странице оплаты. Если платёжка прислала уведомление дважды. Если одно событие попало в два канала. Если событие в полночь по Москве, а смотрит его человек из Калининграда. Сюда же — юридические случаи: удаление персональных данных по 152-ФЗ, маркировка рекламы по 38-ФЗ.
Когда документ написан хорошо, Claude Code не придумывает решения на ходу, а реализует ровно то, что описано. Баги перестают быть бесконечными, токены — улетать в пустоту. Это и есть разница между вайбкодером и AI‑архитектором: первый кидает вайбы и надеется, второй сначала проектирует, потом строит. Инструмент один и тот же.
Что получилось сделать
Первым настоящим продуктом по этой системе стал EventMap — афиша городских мероприятий.
Афиши разбросаны по десяткам Telegram-каналов, сайтов и пабликов. Крупные сервисы заточены под стадионные концерты в Москве, а лекция в коворкинге или локальный фестиваль там теряются. Я собрал всё в одном месте — для всей страны, а не для двух столиц.
EventMap живёт сразу на двух площадках из единого кода:
-
сайт events-map.ru — его индексирует Яндекс, люди приходят по запросам вроде «афиша Краснодар»;
-
приложение в Telegram @EventsMapbot — Mini App, открывается в один тап прямо в мессенджере.
Сейчас в каталоге около 175 городов и больше 6000 событий. Наполняется он почти без моего ручного труда — этим занимается AI-парсер. На сборку ушёл месяц, и ни одной строчки кода я не написал руками: я писал спецификацию и правил результат на человеческом языке — «перенеси кнопку», «добавь фильтр по цене», «почини отображение на телефоне».
Дальше — разбор, как это устроено под капотом. Код я не пишу, но проектирую структуру и принимаю инженерные решения. Их и показываю, вместе с тем, на чём наступил.
Архитектура: на чём всё держится
Фронт и Mini App работают на едином стеке: Next.js 16 на App Router, TypeScript в strict-режиме, Tailwind v4, компоненты на shadcn/ui. Деплой — на Vercel.
Бэкенд — Supabase: PostgreSQL 15, около 22 таблиц, на каждой включён RLS (row-level security), то есть права доступа проверяет сама база, а не код приложения. Схему меняю только через миграции, никаких ручных правок в проде. Свойство, которое это даёт: схема всегда восстанавливается из истории миграций и не расходится с тем, что лежит на сервере.
VPS-сервисы — админ-бот на grammy, parser-worker и scheduler — крутятся на Beget под PM2 через tsx и rsync. Без Docker и без сборки в dist: код заливается как есть и запускается напрямую. Для одиночного проекта это меньше слоёв, в которых можно запутаться.
Авторизация организатора идёт через Telegram initData. Роли разведены: visitor, organizer, admin и отдельная ai_parser — у парсера свой уровень доступа, он не равен живому пользователю.
Парсер: где красивая идея встретилась с реальностью
Самая интересная часть — парсер, который наполняет каталог. В спецификации он описан как отдельный AI-агент.
Первый план был через gram.js и MTProto — официальный протокол Telegram. Он не взлетел. Поэтому парсер скрапит web-превью каналов по адресу t.me/s/<username> через cheerio. У решения есть честное ограничение: так видны только публичные каналы. Я выбрал работающий вариант по крайней мене на сегодня так.
Дальше — очередь на BullMQ поверх Redis. Каждый пост уходит в Anthropic Messages API с задачей вытащить структуру события: название, дату, место, цену, категорию. Если это не анонс — модель так и говорит. Основную работу делает claude-sonnet-4-6, лёгкие задачи уходят на claude-haiku-4-5, плюс включён prompt caching, чтобы не платить за одно и то же повторно. Дубликаты одного события из разных каналов система распознаёт и не плодит.
Итог по наполнению честный и неожиданный: supply здоров, событий хватает. Узкое место — не контент, а спрос и выручка. Органических заявок от организаторов почти нет. Это и есть моя реальная задача сейчас, а не «добавить ещё городов».
Монетизация и баг, который полгода ел подсветку
Платёжную модель я упростил до одного тарифа: любая публикация — 999 ₽, всегда с подсветкой (зелёная рамка и приоритет в ленте до даты события). Любое объявление выходит сразу на обеих площадках.
Цены зашиты прямо в роутах и хранятся в копейках целым числом — так их нельзя подделать с фронта. Отдельного lib/pricing.ts нет, источник истины — сами роуты. Решение спорное, и когда я поднимал цену, всплыл спящий баг: флаг boost_priority_until для веб‑флоу не выставлялся нигде. То есть подсветка, за которую платили, де‑факто не работала почти полгода. Сейчас её ставит approve‑роут. Старый тариф на 300 ₽ ушёл в архив, историю заказов я не переписывал.
Платежи лежат в таблице orders. Рекламные баннеры маркирую по закону — поле erid и реквизиты рекламодателя, на странице это рендерит отдельный компонент AdDisclosure.
Свежий ход — YML‑фид /events-feed.xml для блока «Рекомендации событий» в поиске Яндекса. Ключевое решение: фид это привилегия платящих, а не парсера. Критерий «наше размещение» — source='manual', его ставят и форма сайта, и бот. Таргетинг сделал колонкой show_in_yandex_feed плюс триггер BEFORE INSERT — так оба кодовых пути закрылись без правок формы и бота и без передеплоя VPS. В фид попадают около 146 наших размещений, а 1475 спарсенных исключены: раздавать чужим бесплатный поисковый трафик смысла нет.
Принцип, который спас меня от вранья самому себе
Один сквозной принцип всех сессий: факты сверяю с кодом и продом, а не с заметками. Документация дрейфует и не раз вводила в заблуждение — где‑то Метрика числилась «не подключена», где‑то хвост бота «не закоммичен», где‑то аналитика молча ничего не писала. Поэтому цифры в коммерческих предложениях и отчётах беру прямыми запросами к таблицам просмотров и событий баннеров, а не из старых записей.
Для одиночного проекта это спасение. Заметки врут незаметно. Код и база — нет.
Честно про стадию
Год назад такой продукт — сайт, Telegram‑приложение, парсер и каталог на 175 городов — это команда из трёх‑четырёх человек и несколько месяцев. У меня ушёл месяц, и основные затраты — моё время на спецификацию и подписки на инструменты.
Я не делаю вид, что это денежная машина. Supply работает, техника собрана, а спрос и выручка — впереди. Для человека, который четыре месяца назад вообще не открывал код, это результат, который можно потрогать.
Что дальше
EventMap я не бросаю на запуске — буду растить и делиться обновлениями: что добавил, что сработало, а что нет. Параллельно уже веду переговоры о внедрении AI-разработки в бизнес, несколько проектов сделал. О кейсах расскажу отдельно, когда можно будет показать цифры.
Потрогать результат можно прямо сейчас:
-
сайт — events-map.ru
-
приложение в Telegram — https://t.me/EventsMapbot/app
-
вопросы — лично мне: @Nikolay_Karkach
Если вы собирали продукт с AI и у вас тоже выходила дичь — пишите в комментариях, интересно как у Вас получается, особенно спец которые так же с нуля сделали дело и зарабатывают на этом
ссылка на оригинал статьи https://habr.com/ru/articles/1047664/