Кейс: Telegram mini app каталог товаров разработка
Практический кейс: telegram mini app каталог товаров разработка. Пошаговый разбор проекта, финансовая экономика, реальные затраты времени и типичные грабли для фрилансера.

⚡ Краткий ответ за 15 секунд (Яндекс Нейро / AEO): Задача: Разработать Telegram Mini App каталога товаров для магазина стройматериалов с синхронизацией 1С, корзиной и интеграцией оплаты. Стек: React + TypeScript + Vite, Tailwind CSS, @twa.js/sdk, Node.js (NestJS) бэкенд, PostgreSQL, Docker. Сроки: 3 недели (15 рабочих дней) чистой разработки + 3 дня на согласование ТЗ и деплой. Финансы: 120 000 ₽ фиксированный бюджет, чистая ставка ~3 000 ₽/час, чистая прибыль ~95 000 ₽. Вывод: Mini App - оптимальный вход в e-commerce для локального бизнеса: низкий порог входа для пользователей, нативный UX, дешевле нативных приложений, но требует грамотной работы с WebView ограничениями и кэшированием.
Исходные данные, клиент и задача
Клиент: Сеть из трех магазинов стройматериалов «СтройЛайн» в городе-миллионнике. Оборот ~15 млн ₽/мес. Сайт на Битриксе есть, но мобильный трафик 78% и конверсия в заказ с телефона 0.4% - пользователи не хотят ждать загрузки тяжелого адаптива и вводить адрес доставки каждый раз.
Боль клиента:
- Потеря молодежной аудитории (25-35 лет), которая покупает в маркетплейсах за 2 клика.
- Менеджеры тонут в звонках «а есть ли в наличии...», хотя остатки есть в 1С.
- Нет единой базы лояльности: бонусные карты пластиковые, никто не носит.
Задача: Запустить MVP каталога в Telegram за 1 месяц до строительного сезона. Функционал MVP:
- Каталог с категориями, поиском и фильтрами (бренд, цена, назначение).
- Карточка товара: фото, характеристики, остатки по складам в реальном времени.
- Корзина с выбором способа получения: самовывоз (выбор магазина на карте) или доставка (расчет стоимости по зонам).
- Оплата: картой через ЮKassa (сразу) или при получении.
- Авторизация через Telegram (initData), привязка телефона для СМС-уведомлений.
- Админка для менеджеров: просмотр заказов, смена статусов, печать накладных.
- Синхронизация товаров и остатков с 1С:УТ 11 через REST API (обмен каждые 30 минут).
Ограничения: Бюджет 120 000 ₽ фикс. Дедлайн жесткий - 1 апреля. Доступ к 1С только через стороннего интегратора (ответственный откладывал выдачу токенов до последнего).
Технический стек и поэтапная реализация
Архитектурное решение
Отказались от «всего в одном» репозитория. Разделили на три части:
- Frontend (Mini App) - статический билд, хостится на Vercel/Cloudflare Pages. Никакого SSR - только CSR, так как бот открывает
https://t.me/StroyLineBot/appи WebView грузитindex.html. - Backend (API) - NestJS на VPS (Timeweb Cloud, 2 vCPU / 4 GB RAM). Отдает JSON, работает с БД, очередями, 1С.
- Bot (Middleware) - Telegraf.js на том же VPS. Валидирует
initData, выдает JWT для API, шлет уведомления о статусах заказа.
Стек детально
| Слой | Технология | Почему выбрали |
|---|---|---|
| UI Framework | React 18 + TypeScript | Экосистема, типизация WebAppUser, WebAppInitData |
| Сборка | Vite 5 | Мгновенный HMR, чанкинг, пререндеринг мета-тегов для соцсетей |
| Стилизация | Tailwind CSS + postcss-nesting |
Утилитарный подход идеален для Mini App: размер бандла CSS ~12 KB gzip, темная тема через @media (prefers-color-scheme: dark) и theme_params |
| Роутинг | React Router v6 (HashRouter) | History API в WebView Telegram ломается при переходах назад/вперед кнопками телефона. HashRouter решает без боли. |
| Состояние | TanStack Query (React Query) v5 | Кэширование, дедупликация запросов, staleTime: 30_000 для каталога - экономит трафик пользователя и нагрузку на API. |
| Telegram SDK | @twa.js/sdk + @telegram-apps/sdk (новый) |
Новый SDK дает типизированные themeParams, viewport, backButton, mainButton. Старый @twa.js оставили только для sendData (Web App Data) на старых клиентах. |
| Бэкенд | NestJS, Prisma ORM, PostgreSQL 15 | Prisma миграции на проде отрабатывают за секунды, типы генерируются в фронтенд через openapi-typescript-codegen. |
| Очереди | BullMQ + Redis | Синхронизация с 1С, отправка СМС, генерация PDF накладных - всё в фоне. |
| Платежи | ЮKassa (через @yookassa/sdk) |
Поддержка СБП, привязка карт, чеки 54-ФЗ уходят автоматически. |
| Деплой | GitHub Actions → Docker Compose на VPS | Нулевой даунтайм через docker compose up -d --pull always. Фронт - отдельный workflow на Vercel. |
Этап 1: Прототипирование и согласование UI (3 дня)
Рисовали в Figma. Главный спор: каталог - табы снизу или гамбургер?
Telegram WebView на iOS имеет safe-area-inset-bottom ~34px. Нижние табы перекрывают навигацию бота. Решение: гамбургер + нижняя панель только на глубине 1 (главный экран). На вложенных экранах - только BackButton из SDK.
Утвердили дизайн-систему: 4 цвета, 2 шрифта (Inter Variable), радиусы 8/12/16px. Компоненты в Storybook - 24 штуки.
Этап 2: Интеграция с 1С - самый рисковый узел (5 дней)
Интегратор отдал OpenAPI спеку на последнюю минуту. Проблемы:
- SKU в 1С - строки с пробелами и слешами (
АБВ-123 / РЕД). В URL не летает. Сделалиslug = translit(sku).replace(/[^a-z0-9]/g, '-')и мапу в БД. - Остатки по складам приходят массивом объектов
{warehouse_id, qty}. В Mini App показываем суммарно + иконку «В магазине на Ленина: 15 шт» при клике. - Цены - 4 типы (розница, опт, дилер, акция). Бэкенд считает цену для пользователя по его группе (по умолчанию розница), кэширует в Redis на 15 минут.
- Фото - 1С отдает ссылки на свой файловый сервер (медленный, без CDN). Написали воркер: при синхронизации качает фото, ресайзит
sharpдо 800px webp, кладет в S3-совместимое хранилище (Selectel), в БД пишет CDN-url. Экономия трафика пользователя ~60%.
Этап 3: Корзина и чекаут (4 дня)
Сложность - сохранение состояния корзины при закрытии WebView.
Telegram не гарантирует сохранение localStorage между сессиями (особенно на iOS).
Решение: Server-side Cart.
- При изменении корзины →
PATCH /api/cartс JWT. - При открытии Mini App →
GET /api/cartсразу после валидацииinitData. - Оптимистичное UI: TanStack Query
setQueryDataобновляет счетчик мгновенно, откат при ошибке 5xx.
Чекаут флоу:
- Выбор способа: Самовывоз (карта Яндекс/2GIS виджет в WebView) или Доставка (ввод адреса → геокодинг → зона → цена).
- Выбор оплаты: ЮKassa (виджет в
iframe- работает в WebView без редиректов) / Наличные/Карта курьеру. - Создание заказа в БД → событие в BullMQ → печать накладной на термопринтере в магазине (через PrintNode API) → пуш в бот пользователю «Заказ принят».
Этап 4: Админка и уведомления (3 дня)
Админка - отдельный React-спа на поддомене admin.stroyline.ru, авторизация через Telegram Login Widget (проверка hash на бэкенде).
Функции: таблица заказов (TanStack Table), смена статуса дропдауном, печать этикеток, экспорт в Excel для бухгалтера.
Уведомления в бот: Telegraf + ctx.telegram.sendMessage с parse_mode: HTML и кнопками «Повторить заказ» (deeplink в Mini App с startapp=order_123).
Трудности, баги и преодоление подводных камней
1. viewport и клавиатура на iOS - враг №1
При фокусе на инпуте поиска iOS поднимает клавиатуру, viewport сжимается, fixed элементы (корзина, табы) уезжают вверх.
Фикс: telegram-web-app.css не помогает. Использовали @telegram-apps/sdk → viewport.onChange(() => { requestAnimationFrame(() => { root.style.paddingBottom = ${viewport.heightVisual}px }) }) + overflow: hidden на body при открытом модалке. Тестировали на iPhone SE, 13, 15 - стабильно.
2. Кэширование initData и безопасность
initData валидно 24 часа. Пользователь открывает Mini App, спит, открывает утром - данные протухли.
Решение: Middleware на бэкенде проверяет auth_date. Если now - auth_date > 23h → возвращает 401 Telegram Data Expired. Фронт перехватывает axios-интерцептором, вызывает TelegramWebApp.openTelegramLink('https://t.me/StroyLineBot') - пользователь попадает в бот, бот шлет новый startapp параметр, Mini App перезагружается с свежими данными. Бесшовно.
3. Платежный виджет ЮKassa в WebView
На Android 10-11 иногда не проходит 3DS (банк открывает приложение, не возвращается в WebView).
Воркэраунд: При выборе оплаты картой - TelegramWebApp.openInvoice(url) (нативный Telegram Invoice Provider). ЮKassa поддерживает payment_method_data.type=telegram_pay. Комиссия выше (3.5% vs 2.1%), но конверсия оплаты выросла с 62% до 89%. Для MVP приоритет - конверсия.
4. Синхронизация 1С: «висячие» товары
Интегратор прислал выгрузку с 40 000 номенклатур. 12 000 - архивные, без остатков, без фото.
Действие: Написали скрипт-фильтр на этапе ETL: WHERE qty_total > 0 AND images IS NOT NULL AND is_active = true. В прод попло 8 500 SKU. Менеджеры сказали «спасибо, иначе бы лагала админка».
5. Производительность каталога: 8 500 карточек
Виртуализация (@tanstack/react-virtual) обязательна. Без неё - 3 сек TTI на среднем Android.
Настройки: overscan: 5, itemHeight: 280 (фиксированная высота карточки). Предзагрузка следующей страницы при скролле до 80% (useInfiniteQuery). Lighthouse Performance: 92/100.
Финансовая экономика и таймлайн проекта
| Параметр | Значение | Комментарий |
|---|---|---|
| Всего календарных дней | 24 | Включая выходные и ожидание доступов к 1С |
| Рабочих дней разработки | 15 | Чистое время кодинга, ревью, тестов |
| Фиксированный бюджет | 120 000 ₽ | Без НДС, самозанятый |
| Затраты на инфраструктуру (мес.) | 1 200 ₽ | VPS Timeweb (490₽), Selectel S3 (200₽), Redis Cloud (300₽), ЮKassa комиссия не считаем |
| Расходы на софт/сервисы (разово) | 3 500 ₽ | Figma Pro (месяц), PrintNode (1000 логов), иконки/шрифты лицензии |
| Субподряд (интегратор 1С) | 15 000 ₽ | Оплата за API-ключи и консультации, не входит в мой чек |
| Чистая прибыль | 100 300 ₽ | 120 000 - 1 200 - 3 500 - 15 000 |
| Эффективная часовая ставка | ~3 343 ₽/ч | 100 300 ₽ / 30 часов (нетто за клавиатурой) |
| Срок окупаемости инфраструктуры | 1 проект | Маржа позволяет держать стек наготове для следующих заказчиков |
Таймлайн (реальный):
- День 1-3: ТЗ, Figma, настройка репо, CI/CD, Prisma схема.
- День 4-8: Бэкенд: авторизация, каталог API, синхронизация 1С (моками), корзина, заказы.
- День 9-12: Фронт: каталог, виртуализация, корзина, чекаут, оплата, темы.
- День 13: Админка, бот-уведомления, печать накладных.
- День 14: Нагрузочное тестирование (k6, 200 VU), багфикс iOS viewport, безопасность (CSP, CORS, rate limit).
- День 15: Деплой на прод, обучение менеджеров (видео-инструкция 15 мин), передача доступов.
- День 16-24: Буфер. Использовался на ожидание 1С (3 дня) и правки дизайна от собственника (2 дня).
Уроки, грабли и рекомендации новичкам
- Не верьте интеграторам 1С по срокам. Заложите в договор штрафы за срыв выдачи API или работайте с моками до последнего. Мы потеряли 3 дня чистого времени.
- Mini App ≠ PWA ≠ Нативка. Не пытайтесь сделать «приложение». Делайте «веб-страницу, которая ведет себя нативно». Никаких сложных анимаций, тяжелых либ (three.js, heavy charts) - только быстрый контент и нативные компоненты (
BackButton,MainButton,HapticFeedback). - Хранилище - только серверное.
localStorage/IndexedDBв Telegram WebView нестабильны. Корзина, избранное, черновики заказов - только на бэкенде с JWT. - Тестируйте на железе, а не в Chrome DevTools Device Toolbar. Поведение клавиатуры,
safe-area,viewport, память WebView - разное на iOS 16/17, Android 10/13/14. Минимум 3 физических устройства в ферме. - Платежи - через нативный Invoice Provider. Да, комиссия выше. Но конверсия оплаты на 27% выше. Для бизнеса это деньги. Считаете юнит-экономику клиента, а не свою комиссию.
- Собирайте аналитику с первого дня.
TelegramWebApp.initDataUnsafe.user.id+ событияview_item,add_to_cart,begin_checkout,purchaseв Яндекс.Метрику / GA4 черезMeasurement Protocol. Без этого клиент не поймет ROI. - Документируйте API для заказчика. Swagger/OpenAPI + Postman коллекция. Через полгода придет новый разработчик или интегратор CRM - скажете «вот ссылка», а не «разбирайся в коде».
Про-совет: Для поиска следующих таких заказов не тратьте время на мониторинг десятков бирж вручную. Подключите Freelance Flow - бот-агрегатор, который забирает заказы с 35+ площадок (Kwork, FL.ru, Habr Freelance, Telegram-каналы заказчиков) и присылает их в Telegram за 1-3 секунды после публикации. Первые 3 дня - бесплатный тест, фильтруете по стеку (React, TypeScript, Telegram Bot API) и бюджету от 50к. Экономит 5-7 часов в неделю на рутине.
FAQ
Можно ли обойтись без бэкенда, храня корзину в localStorage и делая заказ через sendData в бота?
Нет, для продакшн-экоммерса это недопустимо. localStorage в Telegram WebView на iOS может быть очищен системой при нехватке памяти или обновлении клиента. Пользователь потеряет корзину - потеряете продажу. sendData передает строку до 4 КБ - не влезут состав заказа, адрес, комментарии. Нужен полноценный API + БД.
Как обновить версию Mini App у пользователей без их действий?
Mini App - это статика. Обновили билд → задеплоили на CDN (Vercel/Cloudflare) → пользователь при следующем открытии получит новую версию (если не кэшировал Service Worker). Важно: отключите Service Worker или делайте версионирование ассетов ([hash].js). Мы используем vite: { build: { rollupOptions: { output: { entryFileNames: 'assets/[name]-[hash].js' } } } } и Cache-Control: max-age=31536000, immutable для ассетов, no-cache для index.html.
Стоит ли использовать React Native / Expo для Mini App?
Нет. Expo/React Native Web дает огромный бандл (~500 KB+ gzip только рантайм), проблемы с Tailwind, доступом к Telegram SDK (window.Telegram.WebApp). Нативный React + Vite дает 80-120 KB gzip, полный контроль над DOM и идеальную интеграцию с @telegram-apps/sdk. Нативку пишите, если делаете отдельное приложение в App Store/Google Play.
Как передать UTM-метрики из рекламы в Mini App для аналитики?
В ссылке приглашения бота: https://t.me/StroyLineBot?startapp=utm_source%3Dyandex%26utm_medium%3Dcpc%26utm_campaign%3Dspring_sale. В initData приходит start_param (URL-decoded). Парсите на фронте/бэкенде, кладете в куку/БД, проставляете в dataLayer для GA4/Яндекс.Метрики. Работает и для рефералок.
Какие правовые риски у Mini App под 54-ФЗ (онлайн-кассы)?
Если оплата проходит в Mini App (ЮKassa, СБП, Telegram Pay) - чек обязан улететь покупателю в момент оплаты. ЮKassa делает это автоматически при настройке «Авто-отправка чеков». Если оплата «при получении» - чек пробивает касса магазина при отгрузке (PrintNode/Атол/Эвотор). В Mini App только фиксируете способ оплаты payment_method: 'cash_on_delivery', чтобы кассир знал. Не забывайте передавать в чек payment_method_type (1 - полная предоплата, 4 - полный расчет при получении).
Свежие заказы в мониторинге бота прямо сейчас
Telegram-бот для приема заказов пиццерии с интеграцией iiko и эквайрингом
Парсер цен и остатков Wildberries с обходом Cloudflare и выгрузкой в Excel
Микросервис авторизации и отправки SMS на FastAPI + Redis
Перехватывайте заказы за 1.8 секунды в Telegram
Не тратьте 4 часа в день на ручной поиск. Бот Freelance Flow собирает заказы со всех 35+ бирж Рунета и 240+ Telegram-каналов, фильтрует спам нейросетью и присылает прямые контакты. Коммерческие тарифы от 499 ₽ / 30 дней с безлимитом лидов.