За последние полтора года я стал участником нескольких сообществ: бизнес-клубы, профессиональные комьюнити, неформальные группы бывших коллег, которые вместе хоЗа последние полтора года я стал участником нескольких сообществ: бизнес-клубы, профессиональные комьюнити, неформальные группы бывших коллег, которые вместе хо

Один фаундер и AI собрали SaaS для Telegram-сообществ. Вот что пошло не так

2026/02/18 11:07
16м. чтение

За последние полтора года я стал участником нескольких сообществ: бизнес-клубы, профессиональные комьюнити, неформальные группы бывших коллег, которые вместе ходят в бани и кальянные. Везде одна и та же картина: активностей много, но организация регистрации и напоминаний — на коленке. Анонс проскакивает в чате, теряется в папке непрочитанных. Организатор лично пишет каждому: «Будешь?» Кто-то собирает деньги за бронь заведения и мучается с табличкой в Google Sheets.

Я решил проверить, можно ли собрать production-SaaS для Telegram-сообществ в одиночку, используя AI-агентов как основную рабочую силу — от написания кода до DevOps и части маркетинга. Не “поиграться с прототипом”, а довести систему до состояния, когда ею пользуются реальные люди.

Ниже — разбор того, что получилось, какие архитектурные решения пришлось принять и какие проблемы возникли при попытке довести AI-сгенерированный код до продакшена.

Рынок, застрявший между лендингом и чатом

Регистрация на мероприятия — задача, решённая десяток раз. Timepad, лендинг на тильде, Leader-ID, и, конечно, Google Forms или уже Яндекс.Формы. Все они работают по одной схеме:

  1. Организатор создаёт лендинг с описанием

  2. Кидает ссылку в Telegram-группу

  3. Участник кликает → открывается браузер → форма → оплата (если платное)

  4. Возвращается в Telegram

Для конференций и концертов подробный лендинг — это плюс. Он вовлекает, объясняет, продаёт. Но форматы мероприятий изменились. Бизнес-завтраки, мастермайнды, нетворкинг-встречи, эфиры, разборы. Для них простого анонса в группе — слишком мало, а лендинга на билетном сервисе — слишком много.

И вот парадокс: аудитория давно живёт в Telegram, а сервисы регистрации всё ещё снаружи. Каждый переход из мессенджера в браузер — это потеря конверсии. Человек кликнул, увидел загрузку, отвлёкся, закрыл.

Чему можно поучиться у инфобиза

Есть индустрия, которая эту проблему решила давно — инфобиз. Регистрация на вебинар через бота, прогревающие цепочки сообщений, оплата внутри Telegram — всё это работает и даёт конверсию в разы выше, чем классический лендинг.

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

MVP за неделю: Vercel, Supabase и первые столкновения с Telegram API

Первый прототип был сделан за неделю. Стек вайбкодера: Vercel для хостинга, Supabase для базы данных и авторизации, Next.js как фреймворк.

Что умел MVP:

  • Регистрация и авторизация админов по email

  • Подключение Telegram-групп через добавление бота

  • Создание страницы регистрации на событие и бота

  • Сбор активности участников из групп

  • Постепенное формирование списка участников

Первый урок пришёл сразу: Telegram API позволяет далеко не всё, что доступно в приложении. Например, нельзя просто вытянуть список всех участников группы. Бот видит только тех, кто пишет сообщения. Хочешь знать, кто в группе — жди, пока люди проявят активность. Это перевернуло логику: вместо «загрузил список» теперь «собираешь по крупицам». Поэтому пришлось сделать импорт истории сообщений из Telegram-группы — чтобы при подключении бота не ждать месяцами, а сразу получить список активных участников и их контекст.

100% кода написал AI

Это был осознанный эксперимент: можно ли реализовать полноценный онлайн-сервис в одиночку, как AI-native фаундер, совмещающий все роли — разработку, маркетинг, DevOps, клиентский сервис?

Инструменты: Cursor как IDE с AI-агентами и Claude как основная модель для генерации кода и обсуждения архитектурных решений.

Весь код Orbo — 100% сгенерирован AI. Но это не значит нажал кнопку и получил сервис. Я много тестировал, проверял, что создаётся в базе данных, задавал вопросы модели, обсуждал принятые решения. AI — это не автопилот, это очень быстрый джуниор, который не устаёт и не обижается на правки.

Более того, на второй месяц работы я держал уже 3 агента, каждого из которых затачивал под определённую роль: разработка продукта, devops-задачи и маркетинг. Это позволяло лучше удерживать контекст и распараллеливать работу.

Три месяца до продакшена: что пошло не так

MVP работал. На демо красиво. Дал реальным пользователям — начались проблемы.

От «работает на демо» до «можно давать реальным людям» прошло три месяца: октябрь–декабрь.

Вебхуки, которые молча умирают

Самый неприятный класс багов — незаметные. Telegram-вебхуки периодически слетали. Платформа переставала получать обновления из групп. Снаружи всё выглядело нормально — интерфейс работал, данные отображались. Просто новые сообщения переставали приходить.

Немного контекста для тех, кто не работал с Telegram Bot API. Вебхук — это URL, на который Telegram шлёт события: сообщения, вступления, реакции и т.д. При регистрации вебхука указываешь allowed_updates — список типов событий, которые хочешь получать. У нас это 9 типов: message, edited_message, channel_post, my_chat_member, chat_member, chat_join_request, message_reaction, callback_query и edited_channel_post.

Вебхук может слететь по десятку причин: тайм-аут ответа, ошибка SSL, перезапуск сервера. Telegram перестаёт слать события, но не сообщает об этом активно. Узнать можно только через getWebhookInfo.

Поэтому появился крон check-webhook: каждые 30 минут дёргает getWebhookInfo, сверяет URL и проверяет свежие ошибки. Если что-то не так, то восстанавливает вебхук с полным списком allowed_updates. Звучит просто, но вот подвох:

AI-агент, реализуя новую фичу (например, обработку реакций), добавлял message_reaction в основной обработчик, но забывал обновить список allowed_updates в крон-задаче восстановления. Следующее автовосстановление «случайно» откатывало список событий, и реакции переставали приходить. Замечаешь через несколько дней, когда тебе задают вопрос: «А почему реакции перестали считаться?»

Текущий мониторинг:

  • Крон check-webhook — каждые 30 минут спрашивает у Telegram «как там вебхук?» через getWebhookInfo и восстанавливает, если URL не тот или есть свежие ошибки. Rate limit: не более 3 попыток в час.

  • Суперадминка — та же информация, но для моих глаз: URL, список allowed_updates, последняя ошибка с временем. Без автоматики, просто чтобы убедиться в статусе.

  • Docker healthcheckwget /api/health каждые 30 секунд. Это не про вебхук, а про живость самого Next.js-процесса. Если упал контейнер — Docker его перезапускает.

  • Крон telegram-health-check — смотрит на поле last_sync_at у каждой группы в базе. Если больше 6 часов нет активности — degraded, больше 24 часов — unhealthy. Это косвенный признак: вебхук может быть «зелёным», но данные в базу всё равно не доходят.

Без достаточного логгирования такие ошибки можно не замечать днями. Помогло одно: регулярный проход клиентских сценариев руками и проверка глазами. Банально — зайти в группу, написать сообщение, создать событие, зарегистрироваться и проверить, что объекты появились в системе, в базе и в логах.

Типы данных, которые врут

Когда три системы — Telegram API, PostgreSQL и Next.js — обмениваются данными, начинается ад типов. Telegram возвращает ID пользователя как число. Next.js достаёт параметр из URL — это строка. В базе у участника три разных идентификатора: внутренний UUID, числовой tg_user_id и ещё id записи. Код сравнивает 123 и "123" — JavaScript говорит «ок», но строгое сравнение или поиск по базе ломается молча.

Ещё хуже — непостоянство формата ответов. Одни запросы к базе возвращают массив объектов, другие — одиночный объект. Если код ожидает массив, а приходит объект — ошибки нет, просто .map() не вызывается, данные не обрабатываются. Или наоборот: запрос вернул массив из одного элемента, а код обращается к .id напрямую — получает undefined. И это не падает с ошибкой. Это просто не записывает данные в базу.

Такие баги не проявляются при тестировании, потому что тестовый сценарий — это один пользователь, одно событие, один запрос. Проблема вылезает, когда у участника есть и регистрация на событие, и сообщения в группе, и заявка на вступление — и в каждом контексте его ID приходит в разном формате. Ты узнаёшь об ошибке через неделю, когда пользователи пишут об ошибках, что ожидаемое действие не происходит.

MiniApp не грузился на мобильном интернете — и я потерял первого клиента

Ноябрь 2025, ещё до замедления Telegram в России. Знакомый организатор сообщества попробовал Orbo, создал событие, кинул ссылку в группу. Участники нажимают кнопку — и MiniApp грузится больше минуты. Или не грузится вообще. Люди закрывают. Организатор пишет мне: «Не работает, мы возвращаемся к табличкам».

На моём ноутбуке и телефоне по Wi-Fi всё летало. Я потратил день, пока не догадался проверить на телефоне через мобильный интернет — страницы открывались почти 1 минуту. В начале думал, что это скорость загрузки либо Vercel, либо Supabase. Или количество запросов к Supabase. Это можно было бы оптимизировать. Но оказалось, что на некоторых провайдерах мобильного интернета — часть запросов просто отваливалась или блокировалась, и оптимизацией это уже не решалось.

Это был один из аргументов за переезд на Selectel. После переезда на российский сервер MiniApp стал открываться за 1–2 секунды даже на любом интернете. Но клиента я к тому моменту уже потерял. Урок: тестировать на разных устройствах и разном интернете с первого дня.

Стабильность > фичи

Пользователи не просили новые функции. Они просили, чтобы существующие работали надёжно. Это, пожалуй, главный урок: в SaaS для управления людьми и событиями потерянные данные = потерянное доверие. Если организатор не видит регистрацию участника — это не баг, это катастрофа.

Переезд: с Vercel на российские серверы

Основная причина переезда — законодательство: хранение и обработка персональных данных на территории РФ. Вторая причина — скорость работы для российских пользователей.

Но переезд оказался масштабнее, чем я ожидал. Supabase имеет собственные API, плюс на него была завязана авторизация и отправка email, и миграция на чистый PostgreSQL потребовала не просто замены коннектора, а переписывания логики запросов для большинства функционала. Это было самое большое и сложное изменение за всю историю проекта. И его тоже делали AI-агенты — но под моим плотным контролем, потому что по мере переписывания каждый раз всё ломалось.

Стек продакшена

Текущая инфраструктура на Selectel:

  • PostgreSQL 16 (Alpine) — с тюнингом под сервер с 32GB RAM

  • Next.js 14 в Docker-контейнере (multi-stage build, standalone mode)

  • Nginx как reverse proxy + SSL через Let's Encrypt

  • GitHub Actions — CI/CD, деплой по пушу в master

  • Node.js 20 — рантайм

Всё завёрнуто в docker-compose. Бэкапы базы, ротация логов, healthcheck-и. Звучит как базовый DevOps, но когда ты один и не имеешь такого опыта вручную — каждый из этих пунктов занимает день. А если что-то падает когда ты не за компом — ты всё равно тот единственный, кто должен это починить.

Архитектура: три бота, один вебхук и 18 кронов

Текстом, потому что таблички псевдографикой от агентов уже кажутся "новым чёрным":

Telegram Cloud │ ┌──────────────┼──────────────┐ │ webhook │ webhook │ нет webhook ▼ ▼ │ ┌─────────────────────────────────────────────────────────┐ │ Сервер в Selectel (32GB RAM) │ │ │ │ ┌───────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Nginx │───>│ Next.js 14 │───>│ PostgreSQL 16│ │ │ │ :80/:443 │ │ :3000 │ │ :5432 │ │ │ └───────────┘ └──────────────┘ └──────────────┘ │ │ │ │ Next.js обрабатывает входящие вебхуки и отправляет │ │ сообщения через Telegram Bot API: │ │ │ │ ┌─────────────┐ ┌────────────┐ ┌─────────────┐ │ │ │ Community │ │ Assist Bot │ │ Event Bot │ │ │ │ Bot │ │ (уведомл.) │ │ (MiniApp) │ │ │ │ webhook │ │ webhook │ │ │ │ │ └─────────────┘ └────────────┘ └─────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ 18 cron-задач: метрики групп, напоминания, │ │ │ │ проверка вебхуков, синхронизация админов, │ │ │ │ анонсы, зоны внимания, дайджесты... │ │ │ └─────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ Пользователи: | Организатор ──> my.orbo.ru (веб-панель) | Участник ──> MiniApp в Telegram (@orbo_event_bot) | Потенциальные клиенты ──> orbo.ru (лендинг)

Три бота — осознанное решение, а не исторический долг:

  • @orbo_community_bot — добавляется в группы как администратор. Получает все события: сообщения, реакции, вступления, выходы. Главный webhook. Отправляет коды авторизации и уведомления в личные сообщения.

  • @orbo_assist_bot — бот для организаторов и админов. Отправляет коды авторизации и уведомления. Уведомления о событиях в группе, требующих внимания: негатив, неотвеченные вопросы.

  • @orbo_event_bot — MiniApp для регистрации на события. Нет webhook-а — только MiniApp, который открывается по кнопке и ходит в API напрямую.

18 cron-задач — от обновления метрик групп каждые 5 минут до еженедельных дайджестов. Самый критичный крон — check-webhook: каждые 30 минут проверяет, что вебхук жив, и восстанавливает его при сбое.

Почему так, а не иначе?

Три бота вместо одного — потому что роли не пересекаются: community-бот сидит в группах и слушает сообщения, assist-бот пишет в личку админу уведомления, event-бот — это только MiniApp без вебхука. Один бот с тремя ролями — это один вебхук-обработчик с ветвлением на всё подряд, и, что важнее для пользователя, одно и то же имя бота и в группе, и в личных сообщениях. Кроны вместо очереди сообщений — потому что одному человеку на текущих объёмах проще пока не задумываться как поддерживать Kafka или RabbitMQ. Next.js API routes по расписанию через внешний cron — проще и достаточно при текущих нагрузках. Всю эту архитектуру можно критиковать, но она работает и поддерживается одним человеком. Когда нагрузка перерастёт кроны — перейду на очереди.

И, да, решения предлагал не я, а агент. Но я задавал вопросы по предлагаемым решениям, и где-то вмешивался или принимал финальное решение.

Как устроен MiniApp для мероприятий

Это, пожалуй, центральная техническая часть — то, ради чего всё затевалось. MiniApp — это веб-приложение, которое открывается прямо внутри Telegram, без перехода в браузер.

Путь участника

Анонс в группе (бот публикует автоматически или админ ручками) │ ▼ Кнопка «Запустить» открывает MiniApp │ ▼ MiniApp загружается внутри Telegram ├── Демонстрируется мини-лендинг анонс мероприятия с кнопкой "Зарегистрироваться" ├── Данные пользователя подтягиваются из Telegram-профиля ├── Форма регистрации (поля настраивает организатор, почти как в google forms) └── Оплата, если событие платное │ ▼ Подтверждение + QR-код билета (если нужно) │ ▼ Напоминания в личку: за 24ч и за 1ч до события (можно настраивать и редактировать)

Техническая механика

MiniApp запускается через deep link вида https://t.me/orbo_event_bot/app?startapp=EVENT\_UUID. Telegram открывает WebView с URL, привязанным к боту через BotFather.

Аутентификация — ключевой момент. Telegram передаёт в MiniApp строку initData, содержащую данные пользователя, подписанные HMAC-SHA256 с использованием токена бота в качестве ключа. На сервере проверяется подпись: вычисляем HMAC от отсортированных параметров и сравниваем с хешем. Если совпало — пользователь настоящий. Если нет — автоматически запускается восстановление вебхука (на случай, если secret token рассинхронизировался).

Что происходит при регистрации:

  1. MiniApp отправляет POST /api/telegram/webapp/events/{id}/register с заголовком X-Telegram-Init-Data

  2. Сервер валидирует подпись initData, извлекает telegram_user_id

  3. Ищет участника в таблице participants по tg_user_id + org_id (мультитенантность — участник одного сообщества не виден другому)

  4. Если участника нет — создаёт, подтягивая имя и username из Telegram-профиля

  5. Вызывает RPC-функцию register_for_event в PostgreSQL — атомарная регистрация с проверкой лимита мест

  6. Генерирует QR-токен для билета

  7. Помечает registration_source: 'telegram_miniapp' — чтобы в аналитике отличать MiniApp-регистрации от веб-формы

Ключевая деталь: данные из Telegram-профиля (имя, фамилия, username) подтягиваются автоматически. Участнику не нужно заполнять «Имя» и «Фамилия» руками — это экономит 2–3 поля и секунд 10–20 на мобильной клавиатуре. Для клубных мероприятий, где все друг друга знают, это превращает регистрацию в один тап.

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

Где AI помогает, а где подводит

Что AI делает хорошо

  • Базовая реализация функционала: API-роуты, CRUD-операции, типовые React-компоненты — AI генерирует гораздо быстрее, чем я пишу спецификацию на функционал.

  • SQL-миграции: описываешь, что нужно изменить в схеме или логике работы с сущностями — получаешь готовый SQL. При 200+ миграциях это критично.

  • Отладка: вставляешь логи сервера — получаешь диагноз и решение. Зачастую со второй итерации, после доработки логгирования.

Где AI подводит

  • Архитектура: AI оптимизирует локально, но не видит проект целиком. Может предложить решение, которое конфликтует с тем, что написано в другом файле.

  • Сложный стейт: цепочка «регистрация → оплата → напоминание → чекин → отмена» — AI путается в ветвлениях и граничных случаях.

  • Контекст внешнего API: ограничения, неактуальность и неполнота документации. Приходится проходить много итераций и лично многократно тестировать неработающее решение, чтобы подобрать следующий шаг.

Конкретные ошибки, которые AI допустил

Теория — это одно. Вот реальные примеры из кодовой базы.

Утечка данных между организациями. Проект мультитенантный — несколько организаций в одной базе. Разделение данных клиентов критично: организатор бизнес-клуба не должен видеть участников чужого сообщества. AI-агент, реализуя синхронизацию Telegram-групп, написал API-эндпоинт, который загружал все группы из базы данных без фильтрации по org_id:

SELECT id, tg_chat_id, title FROM telegram_groups WHERE bot_status IN ('connected', 'pending') -- нет WHERE org_id = ?

Дальше код проверял права через Telegram API (является ли пользователь администратором группы), но сам факт, что все группы всех организаций загружались в один запрос — уязвимость. Если Telegram API недоступен или тормозит, фильтрация не сработает. Правильный паттерн — сначала получить группы через связующую таблицу org_telegram_groups с фильтром WHERE org_id = ?, и только потом работать с ними.

Такие ошибки AI допускает регулярно: он решает текущую задачу (получить список групп), но не учитывает контекст (мультитенантность, изоляция данных). Каждый новый эндпоинт — потенциальная дыра, если не проверять.

Несогласованность между компонентами. Выше я уже описал историю с вебхуками: AI добавляет обработку нового типа события в одном месте, но забывает обновить конфигурацию в другом. Это системная проблема — агент видит файл, с которым работает, но не видит все места, где это изменение должно отразиться.

Итог

Без AI этот проект был бы невозможен для одного человека. С AI — возможен, но потребовал почти полгода вместо месяца, который казался реалистичным на старте. AI не заменяет инженера — он заменяет рутину. Архитектурные решения, приоритизация, тестирование клиентских сценариев — это по-прежнему человек.

Что бы я сделал иначе

Развернул бы на своём сервере с первого месяца. MVP на Vercel + Supabase запустился за неделю — и это казалось победой. Но миграция на собственный PostgreSQL заняла больше времени, чем разработка самого MVP. Supabase использует свои обёртки над SQL, и переписывать пришлось почти всё. Если бы сразу поднял PostgreSQL в Docker — сэкономил бы месяц и нервы. Бонус: проблема с медленной загрузкой MiniApp на мобильном (Supabase в AWS eu-west) тоже бы не случилась.

Не экономил бы на моделях. Запросы к Claude Sonnet дешевле, чем к Opus. Но экономия иллюзорная: на Sonnet задачи решались за большее число итераций и доработок. Точного A/B-теста я не проводил, но суммы, списывающиеся с карты, дали достаточно уверенное ощущение: дешёвая модель на сложных задачах обходится дороже.

Вёл бы маркетинговые материалы в том же проекте, что и код. Первые тексты для сайта и онбординга я обсуждал в отдельном чате с ChatGPT. Ошибка: у него не было контекста проекта — ни структуры продукта, ни того что сделано, а от чего отказались. В свою очередь в проекте в Cursor не хватало описания целевой аудитории, профилей, болей, потребностей. Когда перенёс работу над текстами, сайтом и шагами онбординга в Cursor, качество выросло заметно. AI-агент видит и код, и документацию, и тексты одновременно — и предлагает формулировки, которые соответствуют тому, что продукт реально делает, и тому, какие сегменты целевой аудитории в фокусе.

Не стал бы выносить сайт на отдельную CMS. Была попытка развернуть лендинг на WordPress. Для стартапа, где страниц мало, а правки частые, это оказалось неудобно: две кодовых базы, два деплоя, рассинхрон. Сейчас сайт — это Next.js-роуты на отдельном домене, которые живут в том же проекте и обрабатываются через middleware. Правится за секунды, деплоится вместе с основным кодом.

Что дальше

Замедление Telegram в России — это новая реальность. Я уже адаптирую Orbo под мессенджер Max как дополнительный канал. Если потребуется переезд — контакты участников, история участия в мероприятиях, заполненные формы и история сообщений не потеряются.

Главный вывод за эти месяцы: самое сложное в продукте — не код. Код AI напишет. Самое сложное — выдержать период, когда продукт уже существует, работает, ты тратишь на него каждый день, но он ещё толком никому не нужен. И единственное, что можно делать — продолжать.

Если ведёте сообщество в Telegram и автоматизировали что-то для мероприятий — расскажите в комментариях, как решали. Интересен и чужой опыт, и грабли.

---

Тимофей Горшков — AI-основатель Orbo, ранее основатель и CEO inSales

Источник

Отказ от ответственности: Статьи, размещенные на этом веб-сайте, взяты из общедоступных источников и предоставляются исключительно в информационных целях. Они не обязательно отражают точку зрения MEXC. Все права принадлежат первоисточникам. Если вы считаете, что какой-либо контент нарушает права третьих лиц, пожалуйста, обратитесь по адресу [email protected] для его удаления. MEXC не дает никаких гарантий в отношении точности, полноты или своевременности контента и не несет ответственности за любые действия, предпринятые на основе предоставленной информации. Контент не является финансовой, юридической или иной профессиональной консультацией и не должен рассматриваться как рекомендация или одобрение со стороны MEXC.