Целая автошкола в Telegram-чате

Платформа должна была жить там, где уже находятся пользователи — в Telegram. Не отдельным приложением, требующим загрузки и создания аккаунта, а нативным опытом внутри мессенджера, который они открывают пятьдесят раз в день. Мы построили полноценный Telegram Mini App: бот, отвечающий за онбординг, платежи и уведомления, плюс полноценное приложение на Next.js, встроенное как Telegram WebApp. Пользователь нажимает кнопку в чате — и оказывается внутри отшлифованного интерфейса обучения: главный экран, обзор тем, симулятор экзамена, каталог дорожных знаков, личный профиль — и всё это не выходя из Telegram.

Стек

  • Next.js 14
  • Tailwind CSS
  • FastAPI
  • Telegram

бот, платежи и race conditions

Слой бота на aiogram управляет всем, что происходит в самом чате. Новые пользователи проходят разговорный онбординг: выбирают язык, получают быстрый обзор возможностей и оказываются в Mini App. Платежи за подписку идут через нативный Telegram Payments API, что удерживает чекаут внутри мессенджера — никаких редиректов на внешние страницы оплаты, никаких опасений за форму ввода карты. Но у Telegram Payments есть свои причуды. Подтверждение платежа приходит как webhook-событие, и здесь есть окно race condition: пользователь может закрыть приложение после инициации платежа, но до прихода вебхука. Если бэкенд помечает подписку как активную только по факту получения вебхука, пользователь может снова открыть приложение и несколько секунд видеть «не оплачено». Мы обрабатываем это оптимистичным обновлением статуса на клиенте, подкреплённым серверной верификацией при следующем открытии приложения. Если вебхук так и не пришёл (платёж действительно не прошёл), оптимистичное состояние откатывается.

вьюпорты и нативное ощущение

Фронтенд — приложение на Next.js 14, стилизованное Tailwind, анимированное Framer Motion и GSAP. Управление состоянием — Zustand для глобального состояния (профиль пользователя, подписка, язык) и TanStack Query для всех серверных данных (вопросы, прогресс, знаки). UI должен был ощущаться нативно для Telegram — совпадать с тёмной/светлой темой, учитывать safe area и ограничения вьюпорта платформы — оставаясь при этом полноценным обучающим приложением. Вьюпорты Telegram Mini App печально известны своей непредсказуемостью: разная высота на разных устройствах, разное поведение при открытии клавиатуры, периодические ресайзы при сворачивании шапки Telegram. Мы сожгли на крайних случаях вьюпорта больше времени, чем на любую отдельную фичу. Решением стала комбинация CSS viewport units, resize observer и дебаунсенной корректировки лейаута, не позволяющей контенту прыгать, пока вьюпорт устаканивается.

напоминания через часовые пояса

Планирование push-уведомлений добавило ещё один слой сложности. Бот шлёт ежедневные напоминания об учёбе и уведомления о серии через сообщения Telegram, но пользователи разнесены по нескольким часовым поясам внутри страны. Напоминание в 9 утра по Ташкенту приходит в 10 утра в восточных регионах — терпимо, но напоминание в полночь — нет. Мы храним часовой пояс каждого пользователя (определяется во время онбординга из данных Telegram-клиента, когда это возможно, с ручным фолбэком), и планировщик группирует пакеты уведомлений по смещению часового пояса. Фоновые задачи занимаются и истечением подписок: периодический job проверяет подписки с истёкшим сроком и автоматически понижает доступ, отправляя уведомление «ваша подписка истекла» с кнопкой продления в одно касание.

колесо фортуны и экономика призов

Колесо фортуны — геймификация, которую клиент специально просил для подъёма ежедневной вовлечённости. Пользователи получают одно бесплатное вращение в день с призами от бонусных сообщений к AI-консультанту до промокодов на продление подписки. Инженерным вызовом была не анимация вращения (с ней прекрасно справляется GSAP) — а алгоритм распределения призов. Колесо должно ощущаться захватывающим и честным, но экономика должна быть устойчивой. Мы реализовали взвешенное случайное распределение с дневными и недельными лимитами по тиру призов: дорогие призы (продление подписки) имеют и низкую вероятность, и жёсткие лимиты, поэтому сколько бы людей ни крутили за день, общая раздача остаётся в рамках бюджета. Бэкенд определяет приз до старта анимации — анимация на фронте чисто косметическая, она просто приземляется на тот сегмент, который сервер уже выбрал.

удержание и оборонительная инженерия

Вся система складывается в неожиданно гладкий опыт: пользователь получает утреннее напоминание, тапает по нему, открывает Mini App, изучает тему, проходит тренировочный экзамен, крутит колесо и закрывает Telegram — всё в том же разговорном треде, где он, возможно, ещё и переписывается с друзьями. Клиент заметил значительный рост дневного активного удержания после запуска системы напоминаний и колеса фортуны вместе. Вывод из проекта: Telegram Mini App — мощная, но недоспецифицированная штука. Документация описывает счастливый путь, но реальная фрагментация устройств, крайние случаи платежей и поведение вьюпорта требуют той же оборонительной инженерии, которую вы применили бы к любому кроссплатформенному мобильному приложению. Относиться к этому как к «просто веб-странице в Telegram» — короткий путь к сломанному опыту.