IT & Разработка10 мин чтения

Кейс: Telegram mini app каталог товаров разработка

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

М
Михаил Орлов
Lead Developer & IT-редактор
Опубликовано: 2026-09-23
Кейс: 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% - пользователи не хотят ждать загрузки тяжелого адаптива и вводить адрес доставки каждый раз.

Боль клиента:

  1. Потеря молодежной аудитории (25-35 лет), которая покупает в маркетплейсах за 2 клика.
  2. Менеджеры тонут в звонках «а есть ли в наличии...», хотя остатки есть в 1С.
  3. Нет единой базы лояльности: бонусные карты пластиковые, никто не носит.

Задача: Запустить MVP каталога в Telegram за 1 месяц до строительного сезона. Функционал MVP:

  • Каталог с категориями, поиском и фильтрами (бренд, цена, назначение).
  • Карточка товара: фото, характеристики, остатки по складам в реальном времени.
  • Корзина с выбором способа получения: самовывоз (выбор магазина на карте) или доставка (расчет стоимости по зонам).
  • Оплата: картой через ЮKassa (сразу) или при получении.
  • Авторизация через Telegram (initData), привязка телефона для СМС-уведомлений.
  • Админка для менеджеров: просмотр заказов, смена статусов, печать накладных.
  • Синхронизация товаров и остатков с 1С:УТ 11 через REST API (обмен каждые 30 минут).

Ограничения: Бюджет 120 000 ₽ фикс. Дедлайн жесткий - 1 апреля. Доступ к 1С только через стороннего интегратора (ответственный откладывал выдачу токенов до последнего).


Технический стек и поэтапная реализация

Архитектурное решение

Отказались от «всего в одном» репозитория. Разделили на три части:

  1. Frontend (Mini App) - статический билд, хостится на Vercel/Cloudflare Pages. Никакого SSR - только CSR, так как бот открывает https://t.me/StroyLineBot/app и WebView грузит index.html.
  2. Backend (API) - NestJS на VPS (Timeweb Cloud, 2 vCPU / 4 GB RAM). Отдает JSON, работает с БД, очередями, 1С.
  3. 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.

Чекаут флоу:

  1. Выбор способа: Самовывоз (карта Яндекс/2GIS виджет в WebView) или Доставка (ввод адреса → геокодинг → зона → цена).
  2. Выбор оплаты: ЮKassa (виджет в iframe - работает в WebView без редиректов) / Наличные/Карта курьеру.
  3. Создание заказа в БД → событие в 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. Не верьте интеграторам 1С по срокам. Заложите в договор штрафы за срыв выдачи API или работайте с моками до последнего. Мы потеряли 3 дня чистого времени.
  2. Mini App ≠ PWA ≠ Нативка. Не пытайтесь сделать «приложение». Делайте «веб-страницу, которая ведет себя нативно». Никаких сложных анимаций, тяжелых либ (three.js, heavy charts) - только быстрый контент и нативные компоненты (BackButton, MainButton, HapticFeedback).
  3. Хранилище - только серверное. localStorage/IndexedDB в Telegram WebView нестабильны. Корзина, избранное, черновики заказов - только на бэкенде с JWT.
  4. Тестируйте на железе, а не в Chrome DevTools Device Toolbar. Поведение клавиатуры, safe-area, viewport, память WebView - разное на iOS 16/17, Android 10/13/14. Минимум 3 физических устройства в ферме.
  5. Платежи - через нативный Invoice Provider. Да, комиссия выше. Но конверсия оплаты на 27% выше. Для бизнеса это деньги. Считаете юнит-экономику клиента, а не свою комиссию.
  6. Собирайте аналитику с первого дня. TelegramWebApp.initDataUnsafe.user.id + события view_item, add_to_cart, begin_checkout, purchase в Яндекс.Метрику / GA4 через Measurement Protocol. Без этого клиент не поймет ROI.
  7. Документируйте 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 - полный расчет при получении).

Живая лента: перехват с 35+ бирж в реальном времени

Свежие заказы в мониторинге бота прямо сейчас

Задержка: < 2 сек
Telegram / IT Freelance•14 мин назад

Telegram-бот для приема заказов пиццерии с интеграцией iiko и эквайрингом

Pythonaiogram 3PostgreSQLiiko API
Habr Freelance•28 мин назад

Парсер цен и остатков Wildberries с обходом Cloudflare и выгрузкой в Excel

Pythoncurl_cffiPandas
FL.ru•45 мин назад

Микросервис авторизации и отправки SMS на FastAPI + Redis

FastAPIRedisDocker
⚡ 90% выгодных проектов разбирают в первые 3 минуты после публикации.Получать все заказы в Telegram мгновенно (3 дня бесплатно) →
⚡ Инструмент автоматизации поиска

Перехватывайте заказы за 1.8 секунды в Telegram

Не тратьте 4 часа в день на ручной поиск. Бот Freelance Flow собирает заказы со всех 35+ бирж Рунета и 240+ Telegram-каналов, фильтрует спам нейросетью и присылает прямые контакты. Коммерческие тарифы от 499 ₽ / 30 дней с безлимитом лидов.

Попробовать 3 дня бесплатно →