БлогУслугиКарьера
Обсудить проект
БлогУслугиКарьераОбсудить проект
Mini Apps

Создаём Telegram Mini App на React: пошаговый туториал

Пошаговый туториал по созданию Telegram Mini App на React: от инициализации проекта до деплоя. Telegram SDK, навигация, оплата.

Редакция Feature
Редакция Feature·
20 мар
·
16 мин
·
Создаём Telegram Mini App на React: пошаговый туториал

Введение: почему React — лучший выбор для Mini App

Telegram Mini Apps — это веб-приложения, работающие внутри мессенджера. А раз это веб, значит, для разработки подходят любые современные фреймворки. Но React остаётся самым популярным выбором: огромная экосистема библиотек, знакомый разработчикам синтаксис и отличная совместимость с Telegram WebApp SDK.

В этом туториале мы пройдём весь путь — от npm create до деплоя. Создадим Mini App с реальной функциональностью: авторизацией пользователя, адаптацией под тему Telegram, навигацией, платежами и haptic feedback. Общее представление о платформе Mini Apps можно получить в нашей обзорной статье.

1. Инициализация проекта: Vite + React + TypeScript

Для сборки используем Vite — он обеспечивает мгновенный hot reload и оптимальный продакшен-бандл.

Создание проекта

npm create vite@latest my-mini-app -- --template react-ts
cd my-mini-app
npm install

Структура проекта

Организуем код по функциональным модулям:

src/
├── components/       # UI-компоненты
│   ├── ui/          # Базовые элементы (Button, Input, Card)
│   └── layout/      # Layout-компоненты (Header, Page)
├── hooks/           # Кастомные хуки
│   ├── useTelegram.ts
│   └── useTheme.ts
├── pages/           # Страницы приложения
├── services/        # API-клиент и бизнес-логика
├── types/           # TypeScript-типы
├── utils/           # Утилиты
├── App.tsx
└── main.tsx

Такая структура масштабируется: при росте приложения добавляются новые модули, а не растут существующие файлы.

Настройка Vite

Для корректной работы Mini App нужно настроить несколько параметров Vite:

// vite.config.ts
import {defineConfig} from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
    plugins: [react()],
    server: {
        host: true, // Доступ с мобильного устройства в локальной сети
        port: 3000,
    },
    build: {
        outDir: "dist",
        sourcemap: false,
        rollupOptions: {
            output: {
                manualChunks: {
                    vendor: ["react", "react-dom"],
                },
            },
        },
    },
});

2. Подключение Telegram WebApp SDK

Установка SDK

Telegram предоставляет официальный npm-пакет:

npm install @telegram-apps/sdk-react

Этот пакет включает React-хуки для работы с Telegram API. Альтернативно можно использовать низкоуровневый @telegram-apps/sdk, но React-обёртка удобнее.

Инициализация SDK

Создадим провайдер, который инициализирует SDK при загрузке приложения:

// src/components/TelegramProvider.tsx
import {useEffect, useState, ReactNode} from 'react'
import {init, backButton, miniApp} from '@telegram-apps/sdk-react'

interface Props {
    children: ReactNode
}

export function TelegramProvider({children}: Props) {
    const [ready, setReady] = useState(false)

    useEffect(() => {
        const initApp = async () => {
            try {
                init()
                miniApp.ready()
                setReady(true)
            } catch (error) {
                console.error('Failed to init Telegram SDK:', error)
                // Fallback для разработки в браузере
                setReady(true)
            }
        }
        initApp()
    }, [])

    if (!ready) return <div>Loading
...
    </div>
    return <>{children} < />
}

Обёртка в main.tsx

// src/main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import {TelegramProvider} from './components/TelegramProvider'
import App from './App'
import './index.css'

ReactDOM.createRoot(document.getElementById('root')!).render(
    <React.StrictMode>
        <TelegramProvider>
            <App / >
    </TelegramProvider>
    < /React.StrictMode>,
)

3. Адаптация темы под Telegram

Одно из ключевых требований к Mini App — визуальная интеграция с Telegram. Приложение должно выглядеть как часть мессенджера, а не как чужеродная вставка.

CSS-переменные Telegram

Telegram передаёт цветовую схему через CSS-переменные. Основные переменные:

:root {
    --tg-theme-bg-color: #ffffff;
    --tg-theme-text-color: #000000;
    --tg-theme-hint-color: #999999;
    --tg-theme-link-color: #2481cc;
    --tg-theme-button-color: #5288c1;
    --tg-theme-button-text-color: #ffffff;
    --tg-theme-secondary-bg-color: #efeff3;
}

Глобальные стили

/* src/index.css */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    background-color: var(--tg-theme-bg-color, #ffffff);
    color: var(--tg-theme-text-color, #000000);
    -webkit-font-smoothing: antialiased;
}

a {
    color: var(--tg-theme-link-color, #2481cc);
}

Кастомный хук для темы

Создадим хук, который удобно предоставляет цвета темы в компонентах:

// src/hooks/useTheme.ts
import {useMemo} from "react";
import {useThemeParams} from "@telegram-apps/sdk-react";

export function useAppTheme() {
    const themeParams = useThemeParams();

    return useMemo(
        () => ({
            bgColor: themeParams.bgColor || "#ffffff",
            textColor: themeParams.textColor || "#000000",
            hintColor: themeParams.hintColor || "#999999",
            linkColor: themeParams.linkColor || "#2481cc",
            buttonColor: themeParams.buttonColor || "#5288c1",
            buttonTextColor: themeParams.buttonTextColor || "#ffffff",
            secondaryBgColor: themeParams.secondaryBgColor || "#efeff3",
            isDark: themeParams.bgColor
                ? parseInt(themeParams.bgColor.slice(1), 16) < 0x808080
                : false,
        }),
        [themeParams]
    );
}

Теперь компоненты автоматически подстраиваются под светлую и тёмную тему Telegram. Если вас интересуют продвинутые приёмы адаптивной вёрстки, рекомендуем нашу статью про адаптивный дизайн с Tailwind CSS.

4. Навигация в Mini App

Выбор подхода

В Mini App есть нативная кнопка «Назад» в шапке Telegram. Это значит, что навигация должна быть интегрирована с этой кнопкой. Используем react-router-dom:

npm install react-router-dom

Настройка роутера

// src/App.tsx
import {BrowserRouter, Routes, Route, useNavigate, useLocation} from 'react-router-dom'
import {useEffect} from 'react'
import {backButton} from '@telegram-apps/sdk-react'
import {HomePage} from './pages/HomePage'
import {ProductPage} from './pages/ProductPage'
import {CartPage} from './pages/CartPage'

function NavigationHandler() {
    const navigate = useNavigate()
    const location = useLocation()

    useEffect(() => {
        if (location.pathname !== '/') {
            backButton.show()
        } else {
            backButton.hide()
        }

        const off = backButton.onClick(() => {
            navigate(-1)
        })

        return () => off()
    }, [location, navigate])

    return null
}

export default function App() {
    return (
        <BrowserRouter>
            <NavigationHandler / >
        <Routes>
            <Route path = "/"
    element = { < HomePage / >
}
    />
    < Route
    path = "/product/:id"
    element = { < ProductPage / >
}
    />
    < Route
    path = "/cart"
    element = { < CartPage / >
}
    />
    < /Routes>
    < /BrowserRouter>
)
}

Важные нюансы навигации

Несколько моментов, которые часто упускают:

  • Не используйте хеш-роутинг — BrowserRouter лучше работает с Telegram
  • Кнопка «Назад» должна быть предсказуемой — пользователь ожидает, что она вернёт на предыдущий экран
  • Глубина навигации — старайтесь не делать более 3–4 уровней вложенности
  • Анимации переходов — добавляют ощущение нативности, используйте framer-motion

5. Аутентификация пользователя

Как работает initData

При запуске Mini App Telegram передаёт подписанную строку initData, содержащую информацию о пользователе. Эту строку нужно проверить на бэкенде — чтобы убедиться, что данные подлинные.

Получение initData на фронте

// src/hooks/useAuth.ts
import {useLaunchParams} from "@telegram-apps/sdk-react";

export function useAuth() {
    const launchParams = useLaunchParams();

    const initData = launchParams.initDataRaw;
    const user = launchParams.initData?.user;

    return {
        initData,
        user,
        isAuthenticated: !!user,
        userId: user?.id,
        firstName: user?.firstName,
        lastName: user?.lastName,
        username: user?.username,
        isPremium: user?.isPremium,
        languageCode: user?.languageCode,
        photoUrl: user?.photoUrl,
    };
}

Валидация на бэкенде (Node.js)

// server/auth.ts
import crypto from "crypto";

function validateInitData(initData: string, botToken: string): boolean {
    const params = new URLSearchParams(initData);
    const hash = params.get("hash");
    params.delete("hash");

    const dataCheckString = Array.from(params.entries())
        .sort(([a], [b]) => a.localeCompare(b))
        .map(([key, value]) => `${key}=${value}`)
        .join("\n");

    const secretKey = crypto
        .createHmac("sha256", "WebAppData")
        .update(botToken)
        .digest();

    const calculatedHash = crypto
        .createHmac("sha256", secretKey)
        .update(dataCheckString)
        .digest("hex");

    return calculatedHash === hash;
}

Эта проверка гарантирует, что данные пришли именно от Telegram и не были подменены. Без неё любой может подделать запрос к вашему API.

Нужна разработка Mini App?

Создадим Mini App на React с полным функционалом

Заказать Mini App

6. Взаимодействие с бэкендом

API-клиент

Создадим обёртку для fetch с автоматической передачей initData:

// src/services/api.ts
const API_URL = import.meta.env.VITE_API_URL || "https://api.example.com";

class ApiClient {
    private initData: string = "";

    setInitData(data: string) {
        this.initData = data;
    }

    async request<T>(path: string, options: RequestInit = {}): Promise<T> {
        const response = await fetch(`${API_URL}${path}`, {
            ...options,
            headers: {
                "Content-Type": "application/json",
                "X-Init-Data": this.initData,
                ...options.headers,
            },
        });

        if (!response.ok) {
            throw new Error(`API Error: ${response.status}`);
        }

        return response.json();
    }

    get<T>(path: string) {
        return this.request<T>(path);
    }

    post<T>(path: string, body: unknown) {
        return this.request<T>(path, {
            method: "POST",
            body: JSON.stringify(body),
        });
    }
}

export const api = new ApiClient();

Хук для загрузки данных

// src/hooks/useApi.ts
import {useState, useEffect} from "react";
import {api} from "../services/api";

export function useApi<T>(path: string) {
    const [data, setData] = useState<T | null>(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);

    useEffect(() => {
        api
            .get<T>(path)
            .then(setData)
            .catch((e) => setError(e.message))
            .finally(() => setLoading(false));
    }, [path]);

    return {data, loading, error};
}

7. Платежи через Telegram Stars

Как работают Telegram Stars

Telegram Stars — внутренняя валюта платформы. Пользователи покупают Stars через Apple Pay или Google Pay, а затем тратят их в Mini Apps. Разработчик получает средства и может вывести их через Fragment.

Создание инвойса на бэкенде

// server/payments.ts
import {Bot} from "grammy";

const bot = new Bot(process.env.BOT_TOKEN!);

async function createInvoice(
    userId: number,
    title: string,
    description: string,
    amount: number
) {
    const invoiceLink = await bot.api.createInvoiceLink(
        title,
        description,
        JSON.stringify({userId, amount}), // payload
        "", // provider_token (пусто для Stars)
        "XTR", // currency (XTR = Stars)
        [{label: title, amount}] // prices
    );

    return invoiceLink;
}

Оплата на фронте

// src/hooks/usePayment.ts
import {miniApp} from "@telegram-apps/sdk-react";
import {api} from "../services/api";

export function usePayment() {
    const pay = async (productId: string) => {
        // Получаем ссылку на инвойс с бэкенда
        const {invoiceLink} = await api.post<{ invoiceLink: string }>(
            "/payments/create",
            {productId}
        );

        // Открываем окно оплаты Telegram
        const result = await miniApp.openInvoice(invoiceLink);

        if (result === "paid") {
            // Оплата успешна
            return true;
        }

        return false;
    };

    return {pay};
}

Обработка webhook

Telegram отправит webhook при успешной оплате. Бэкенд должен подтвердить получение:

// server/webhook.ts
bot.on("pre_checkout_query", async (ctx) => {
    // Проверяем, можем ли выполнить заказ
    await ctx.answerPreCheckoutQuery(true);
});

bot.on("message:successful_payment", async (ctx) => {
    const payment = ctx.message.successful_payment;
    const payload = JSON.parse(payment.invoice_payload);

    // Выдаём пользователю оплаченный товар/услугу
    await fulfillOrder(payload.userId, payload.amount);

    await ctx.reply("Оплата прошла успешно!");
});

8. Haptic Feedback и нативные функции

Haptic Feedback

Вибрационная обратная связь делает Mini App ощутимо нативнее. Telegram предоставляет три типа:

// src/hooks/useHaptic.ts
import {hapticFeedback} from "@telegram-apps/sdk-react";

export function useHaptic() {
    return {
        // Лёгкий тап — для нажатия кнопок
        impact: (
            style: "light" | "medium" | "heavy" | "rigid" | "soft" = "light"
        ) => {
            hapticFeedback.impactOccurred(style);
        },
        // Уведомление — для результатов действий
        notification: (type: "success" | "warning" | "error") => {
            hapticFeedback.notificationOccurred(type);
        },
        // Изменение выбора — для переключателей
        selectionChanged: () => {
            hapticFeedback.selectionChanged();
        },
    };
}

Пример использования в компоненте

function ProductCard({product}: { product: Product }) {
    const {impact, notification} = useHaptic()
    const {pay} = usePayment()

    const handleBuy = async () => {
        impact('medium')
        const success = await pay(product.id)
        notification(success ? 'success' : 'error')
    }

    return (
        <div className = "product-card" >
            <h3>{product.name} < /h3>
            < p > {product.price}
    Stars < /p>
    < button
    onClick = {handleBuy} > Купить < /button>
        < /div>
)
}

QR-сканер

import {qrScanner} from "@telegram-apps/sdk-react";

async function scanQR() {
    const result = await qrScanner.open({text: "Наведите камеру на QR-код"});
    if (result) {
        console.log("Scanned:", result);
    }
    qrScanner.close();
}

Cloud Storage

import {cloudStorage} from "@telegram-apps/sdk-react";

// Сохранить данные
await cloudStorage.setItem("cart", JSON.stringify(cartItems));

// Загрузить данные
const saved = await cloudStorage.getItem("cart");
const cart = saved ? JSON.parse(saved) : [];

9. Тестирование и отладка

Локальная разработка

Для тестирования Mini App локально нужен HTTPS. Используем ngrok или Cloudflare Tunnel:

# Запускаем dev-сервер
npm run dev

# В другом терминале — туннель
npx cloudflared tunnel --url http://localhost:3000

Полученный HTTPS-URL указываем в @BotFather как URL Mini App.

Debug Mode

В Telegram Desktop можно включить Debug Mode: правый клик по Mini App и выбрать «Inspect Element». Откроется Chrome DevTools с полным доступом к консоли, сети и элементам.

На мобильных устройствах используйте eruda — встроенную консоль для мобильного веба:

npm install eruda
// Только для разработки!
if (import.meta.env.DEV) {
    import("eruda").then((eruda) => eruda.default.init());
}

Тестирование без Telegram

Для юнит-тестов и разработки в браузере создадим мок Telegram SDK:

// src/utils/mockTelegram.ts
export function mockTelegramEnv() {
    if (typeof window !== "undefined" && !window.Telegram) {
        window.Telegram = {
            WebApp: {
                initData: "mock_init_data",
                initDataUnsafe: {
                    user: {
                        id: 12345,
                        first_name: "Test",
                        last_name: "User",
                        username: "testuser",
                    },
                },
                ready: () => {
                },
                expand: () => {
                },
                close: () => {
                },
                // ... другие методы
            },
        } as any;
    }
}

Обсудим ваш проект?

Оставьте контакты — перезвоним и обсудим задачу

10. Деплой Mini App

Вариант 1: Vercel

Самый простой способ задеплоить Mini App:

npm install -g vercel
vercel

Vercel автоматически определит Vite-проект, соберёт его и задеплоит. Вы получите HTTPS-URL, который можно сразу указать в @BotFather.

Вариант 2: Cloudflare Pages

Бесплатный хостинг с отличной производительностью:

npm install -g wrangler
wrangler pages deploy dist

Вариант 3: VPS с Nginx

Для полного контроля можно разместить Mini App на VPS:

server {
    listen 443 ssl;
    server_name mini-app.example.com;

    ssl_certificate /etc/letsencrypt/live/mini-app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mini-app.example.com/privkey.pem;

    root /var/www/mini-app/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

Настройка бота в BotFather

После деплоя настройте бота:

  1. Откройте @BotFather
  2. Выберите бота: /mybots -> ваш бот
  3. Bot Settings -> Menu Button -> укажите URL Mini App
  4. Или Bot Settings -> Mini App -> укажите URL

CI/CD

Автоматизируйте деплой через GitHub Actions:

name: Deploy Mini App
on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npm run build
      - uses: cloudflare/pages-action@v1
        with:
          apiToken: ${{ secrets.CF_API_TOKEN }}
          accountId: ${{ secrets.CF_ACCOUNT_ID }}
          projectName: my-mini-app
          directory: dist

Подробнее о настройке мониторинга и CI/CD для веб-приложений можно прочитать в нашей отдельной статье.

Архитектурные решения и рекомендации

Производительность

Mini App работает в WebView, поэтому каждый килобайт на счету:

  • Минимизируйте бандл — используйте tree shaking, lazy loading для страниц
  • Оптимизируйте изображения — WebP, lazy loading, правильные размеры
  • Кэшируйте данные — используйте React Query или SWR для кэширования API-запросов
  • Избегайте тяжёлых библиотек — date-fns вместо moment, zod вместо yup

Оффлайн-поддержка

Mini App может ограниченно работать офлайн через Service Worker. Кэшируйте статику и критичные данные.

Аналитика

Подключите аналитику для понимания поведения пользователей:

  • Telegram предоставляет базовую статистику через @BotFather
  • Для детальной аналитики используйте Amplitude или Mixpanel
  • Отслеживайте воронку: открытие -> взаимодействие -> конверсия

Заключение

Мы прошли полный путь создания Telegram Mini App на React: от инициализации проекта до деплоя. Ключевые моменты:

  1. Vite + React + TypeScript — оптимальный стек для Mini App
  2. Telegram SDK — предоставляет всё необходимое для интеграции
  3. Адаптация темы — обязательна для нативного ощущения
  4. initData — безопасная аутентификация без регистрации
  5. Telegram Stars — простой способ монетизации
  6. Haptic feedback — мелочь, которая делает приложение живым

Если вам нужна помощь с разработкой Mini App — обращайтесь. Мы создаём Mini Apps на React с полным циклом: от проектирования до запуска и поддержки. Также можем подключить вашу IT-инфраструктуру для бесперебойной работы приложения.

Обсудим ваш проект?

Оставьте контакты — перезвоним и обсудим задачу

Содержание
  • Введение: почему React — лучший выбор для Mini App
  • 1. Инициализация проекта: Vite + React + TypeScript
  • 2. Подключение Telegram WebApp SDK
  • 3. Адаптация темы под Telegram
  • 4. Навигация в Mini App
  • 5. Аутентификация пользователя
  • 6. Взаимодействие с бэкендом
  • 7. Платежи через Telegram Stars
  • 8. Haptic Feedback и нативные функции
  • 9. Тестирование и отладка
  • 10. Деплой Mini App
  • Архитектурные решения и рекомендации
  • Заключение
Поделиться:

Похожие статьи

Вы пишете Telegram Mini App неправильно. Вот доказательство
Mini Apps

Вы пишете Telegram Mini App неправильно. Вот доказательство

12 мин
Как создать Telegram Mini App: полная инструкция для разработчика
Mini Apps

Как создать Telegram Mini App: полная инструкция для разработчика

14 мин
VK Mini Apps или Telegram: где бизнес зарабатывает больше в 2026
Mini Apps

VK Mini Apps или Telegram: где бизнес зарабатывает больше в 2026

11 мин
Feature IT

Feature IT — платформа по обучению программированию и разработке цифровых продуктов. Мы создаём современные веб-решения для бизнеса и обучаем этому других!

Политика конфиденциальностиПользовательское соглашение

О компании

  • Блог
  • Карьера

Услуги разработки

  • Разработка сайтов под ключ
  • Веб-приложения на React/Next.js
  • Telegram-боты для бизнеса
  • Mini Apps (Telegram, VK)
  • SEO-оптимизированные сайты
  • Автоматизация бизнес-процессов
  • Поддержка и развитие IT-продуктов

Обучение

  • Курс Python с нуля
  • Алгоритмы и структуры данных
  • Паттерны проектирования
  • Подготовка к собеседованиям в IT
  • Практика на реальных проектах

Инструменты

  • Генератор UTM-меток
  • Счётчик символов