edit_square igindin

MeetCal: почему я сделал Calendly внутри Telegram

Зачем уходить из Telegram для записи на встречу? MeetCal — планирование прямо в чате.

Ilya Gindin

Был конкретный момент, который меня сломал.

Кто-то пишет мне в Telegram: «созвонимся на этой неделе?» Я отвечаю: «конечно, вот мой Calendly». Они кликают, открывается браузер, на мобильном грузится медленно, может попросить создать аккаунт, может зависнуть. Через пять минут они возвращаются в Telegram, чтобы подтвердить слот. Весь разговор теперь разбит между двумя приложениями и вкладкой браузера.

Это происходит десятки раз в неделю. Я построил MeetCal, потому что устал от этого разрыва.

Проблема с Calendly в Telegram

Calendly нормальный. Делает что обещает. Но в него вшито продуктовое допущение, что запись на встречу — это самостоятельная задача, за которой целенаправленно идут, как при покупке авиабилета.

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

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

Что делает MeetCal

Хозяин один раз настраивает доступность в боте. После этого можно делиться карточкой записи прямо в переписке — напечатать @MeetCalBot в любом чате Telegram, и он вставляет карточку с превью прямо в разговор. Гость нажимает на неё, внутри Telegram открывается Mini App, выбирает слот, готово. Никакого браузера, никакой почты, никакой регистрации.

Подтверждение и напоминания приходят как сообщения Telegram. Весь цикл — предложить, записаться, подтвердить, напомнить — остаётся в одном месте.

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

Самая сложная техническая проблема

Приложение на React + Vite. Telegram Mini Apps дают доступ к WebApp.MainButton — кнопке внизу экрана, которая плавает над контентом. Это основная кнопка действия почти в каждом Mini App.

API императивный: MainButton.show(), MainButton.hide(), MainButton.setText('Забронировать слот'), MainButton.showProgress(). Вызываешь методы — Telegram занимается рендерингом.

React декларативный. Ты описываешь состояние, React решает, что рендерить.

Это несоответствие породило конкретный баг: каждый раз, когда менялось состояние компонента — даже состояние, не связанное с кнопкой — кнопка мигала. Она исчезала на один кадр, прежде чем снова появиться с правильным текстом. На экране телефона это выглядело как поломка.

Корень проблемы: у меня был один useEffect, следивший за всем состоянием, связанным с кнопкой, и вызывавший show(), а затем setText() при каждом рендере. Краткий hide() между рендерами был виден.

Решение — разбить хук на отдельные эффекты с отдельными массивами зависимостей. Один эффект запускается только при монтировании: инициализирует кнопку и вешает обработчик клика. Отдельный эффект запускается только при изменении текста кнопки или состояния загрузки — и никогда не вызывает hide(), только setText() и showProgress(). Видимость управляется отдельно, через свой эффект, который срабатывает только при изменении флага видимости.

Три эффекта вместо одного. У каждого — минимальный массив зависимостей. Мигание прекратилось.

Мелочь, но её изоляция заняла полдня. Именно такие вещи определяют, ощущается ли приложение нативным или кривым.

Что Mini App платформа делает правильно и неправильно

Правильно: дистрибуция бесплатная. Если бот работает, люди находят его через инлайн-поиск. Никакого ревью App Store, никакого шага с установкой. Телеграмовские UI-примитивы — MainButton, BackButton, хаптическая обратная связь, нативный шеринг — достаточны для построения чего-то, что ощущается как настоящее приложение.

Неправильно: дебаггинг — боль. Ошибки в Mini App появляются способами, которые трудно отследить. Объект WebApp ведёт себя по-разному на разных Telegram-клиентах (десктоп, iOS, Android) — и это не задокументировано. Я потратил день на дебаггинг проблемы с лейаутом, которая воспроизводилась только на Android, потому что вычисление высоты viewport учитывает клавиатуру на одной платформе и не учитывает на другой.

Платформа молодая. Это чувствуется. Но ограничения толкают к более простым интерфейсам, что обычно хорошо.

Текущее состояние

У MeetCal три тарифа: бесплатный (базовая запись, ограниченное число слотов в месяц), Starter и Pro. Платные тарифы открывают повторяющуюся доступность, настраиваемые буферы между встречами и несколько других вещей, о которых спрашивают продвинутые пользователи.

Монетизация через Telegram Stars — внутреннюю валюту Telegram. Это органично, потому что пользователи никогда не покидают платформу для оплаты. Конверсия из бесплатного в платное ранняя, но те, кто платит, используют продукт серьёзно.

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

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

Ещё: нужно было внимательнее читать changelog Telegram Mini Apps перед стартом. Между началом разработки и выпуском произошли изменения API, из-за которых пришлось переписывать части слоя авторизации. Урок: считай платформу нестабильной, пока не выпустишь хотя бы одну версию.

Базовая ставка всё ещё держится. Мессенджеры — там живёт внимание. Запись на встречи тоже должна жить там.

← стрелки или свайп →