Введение: почему 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.




