Как создать свое первое приложение Telegram mini app: Next.js, React, Telegram SDK
В этом гайде я покажу как создать Web интерфейс для вашего бота в Telegram:
⚙️ Как создать Next.js проект (BFF — backend for frontend)
☁️ Deploy проект на Vercel
🤖 Как добавить Telegram Mini app для вашего бота.
🔐 Как авторизировать юзера через Telegram’s Web App initData
💬 Как использовать основные функции Telegram SDK: Поделиться, задать нативные стили, как управлять навигацией(кнопкаи или жест "назад")
💡 Как использовать нативные всплывающие окна в Телеграм.
В конце этого гайда у вас будет готовое приложение Telegram Mini App, которое открывается из вашего бота.
🧱 1. Настройка проекта

🛠 Что нам понадобится?
Создать бота с помощью @BotFather и получить ваш
BOT_TOKEN

2. Создать приложение Next.js
Откройте терминал в папке вашего проекта и выполните команду ниже и следйте инструкциям установки проекта.
npx create-next-app@latest
🏗️ Использование Next.js как BFF (Backend-for-Frontend) с помощью App Router. Ниже структура проекта, где лежат фронтенд страницы, а где бэкэнд эндпоинты.

3. Опубликовать проект на GitHub
Перейдите на GitHub, создайте новый репозиторий и следуйте инструкциям в разделе Quick setup, чтобы отправить ваш локальный проект в этот репозиторий.
4. Разверните (задеплойте) ваше приложение на Vercel.
Telegram не размещает ваш сайт — ваш Mini App должен быть размещён на общедоступном хостинге.
Создайте аккаунт на Vercel
Привяжите свой GitHub-аккаунт
Выберите только что созданный репозиторий
Следуйте инструкциям, чтобы развернуть проект
На этом этапе ваше приложение уже должно быть доступно в интернете — и готово к привязке к вашему Telegram-боту.
Также оно будет автоматически переразвёртываться после каждого изменения в удалённом репозитории.
🪄 2. Set Up a Mini App
✅ Метод 1: через команду /newapp
Отправьте команду
/newapp
боту @BotFatherВыберите вашего бота (например,
@YourAppBot
)Укажите название и описание для вашего Web App
Вставьте URL размещённого Mini App (например, ссылку с Vercel)
⚙️ Метод 2: через веб-интерфейс BotFather (приложение Mini App)
Откройте приложение BotFather Mini App(кнопка открыть в боте)
Перейдите в раздел My Bots и выберите нужного бота
Перейдите в: Settings → Mini Apps
Нажмите Main App, включите его и вставьте URL вашего Mini App
(Опционально) Создайте Direct Link — это ссылка, которая будет напрямую открывать Mini App в Telegram (например,
t.me/your_bot_name/...
)(Опционально) Включите кнопку меню, это кнопка слева внутри вашего бота.
После настройки кнопка «Open» справа будет запускать ваш Mini App прямо внутри Telegram 🎉

🔐 3. Авторизация пользователя с помощью Telegram Mini App SDK
Frontend: Получите
initData
с помощью SDK и отправьте его на ваш backend через API-запрос.Backend: Проверьте
initData
, используя токен вашего бота.Если проверка успешна: пользователь авторизован! Вы можете доверять данным пользователя, содержащимся в
initData
.
Установите SDK:
npm install @telegram-apps/sdk-react
Поскольку Telegram внедряет объект Telegram
только в браузере, необходимо использовать SDK только внутри клиентского компонента — иначе возникнут проблемы с серверным рендерингом (SSR).
Используйте next/dynamic
, чтобы импортировать логику Telegram с отключённым SSR:
const TelegramInit = dynamic(() => import('../telegram/client/TelegramInit'), {
ssr: false,
});
Сохраните rawInitData
для авторизации и отправляйте его на ваш backend для авторизации API-запросов.
import { useRawInitData } from '@telegram-apps/sdk-react';
export default function TelegramInit() {
const rawInitData = useRawInitData();
useEffect(() => {
if (rawInitdata) {
localStorage.setItem('token', rawInitdata);
}
}, [rawInitdata]);
}
const res = await fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('token')}`,
},
body: body ? JSON.stringify(body) : undefined,
});
Также вы можете получить полезную информацию о пользователе из Telegram (first_name, last_name, is_bot, photo_url и др.).
import { parse } from '@telegram-apps/init-data-node/web';
const initData = localStorage.getItem('token');
if (initData) {
try {
const parsedData = parse(initData);
if (parsedData.user) {
createUserInDB(parsedData.user);
setUser(parsedData.user);
}
} catch (error) {
console.error('Failed to parse user data:', error);
}
Проверьте initData
на сервере с помощью Telegram Mini Apps SDK:
token
— этоinitData
, который вы получаете из заголовков запросаBOT_TOKEN
— токен вашего бота, полученный от BotFather
import { isValid } from '@telegram-apps/init-data-node/web';
...
const isAuthorized = isValid(token, process.env.BOT_TOKEN!);
Если проверка прошла успешно, вы можете безопасно использовать данные пользователя для операций с базой данных.
🔐 Не забудьте: настройте переменную окружения BOT_TOKEN
Чтобы безопасно использовать токен вашего бота как в среде разработки, так и в продакшене:
🧪 1. Добавьте его в локальное окружение
Создайте файл .env.local
в корне вашего Next.js проекта и добавьте в него:
BOT_TOKEN=your_telegram_bot_token_here
This keeps your token out of version control and safe from exposure.
☁️ 2. Добавьте его в переменные окружения Vercel (Environment Variables)
Чтобы ваш бот работал в продакшене:
Перейдите в панель управления вашего проекта на Vercel
Откройте вкладку Settings
Выберите раздел Environment Variables
Добавьте новую переменную:
Name:
BOT_TOKEN
Value: ваш реальный токен бота
Не забудьте после этого переразвернуть (redeploy) проект, чтобы переменная стала доступна во время выполнения.
📤 4. Как поделиться из Telegram Mini App
Фронтенд: пользователь нажимает «Поделиться» → отправьте данные на
/api/share
Бэкенд: вызовите
savePreparedInlineMessage
→ получите ID сообщенияФронтенд: вызовите
shareMessage({ id })
, передав полученный ID сообщения
Frontend:
import { shareMessage } from '@telegram-apps/sdk-react';
// send info to the backend
const response = await shareTodo(todoId, userId, title, description);
if (response.ok) {
// get event id
const data = await response.json();
if (shareMessage.isAvailable()) {
// share message
await shareMessage(data.id);
}
}
Backend:
На вашем бэкенде получите данные и обратитесь к API-методу savePreparedInlineMessage
для сохранения подготовленного сообщения.
const shareMessage = {
user_id: userId,
result: {
type: 'photo',
id: `todo-${todoId}`,
photo_url: '<https://example.com/photo.jpg>',
thumbnail_url: '<https://example.com/thumb.jpg>',
title: `📝 ${todoTitle}`,
description: todoDescription || 'A task from my Mini App',
caption: `**${todoTitle}**\\n\\n${todoDescription || ''}`,
parse_mode: 'Markdown',
},
};
// send reuest to Telegram Bot API
const result = await savePreparedInlineMessage(shareMessage);
return NextResponse.json({ id: result.id });
📱 5. Некоторые компоненты Telegram SDK
🔙 Поведение кнопки «Назад»
Если у вашего Mini App несколько страниц или маршрутизация, возможно, вы захотите включить навигацию назад. По умолчанию кнопка «Назад» в Telegram не ведёт себя как кнопка браузера — её нужно явно инициализировать и контролировать.
На тех страницах, где должна быть видна кнопка «Назад», её нужно показывать; на остальных — скрывать. Иначе при нажатии кнопки приложение закроется, вместо того чтобы вернуться на предыдущую страницу.
❌ Поведение при закрытии
Если вы хотите напомнить пользователям сохранить данные перед закрытием приложения, можно включить подтверждение закрытия. Это помогает избежать случайной потери несохранённых изменений, запрашивая у пользователя подтверждение перед выходом.
🎨 Компонент Mini App
Чтобы настроить ваш Mini App — например, задать цвета заголовка или фона — или использовать методы для проверки статуса, такие как проверка, активен ли Mini App, сначала необходимо инициализировать (смонтировать) компонент Mini App. Только после монтирования можно безопасно вызывать эти методы.
'use client';
import { useEffect } from 'react';
import {
backButton,
closingBehavior,
init,
miniApp,
useRawInitData,
} from '@telegram-apps/sdk-react';
export default function TelegramInit() {
const rawInitdata = useRawInitData();
useEffect(() => {
try {
init(); // Initialize Telegram SDK
if (backButton.mount.isAvailable()) {
backButton.mount();
backButton.onClick(() => {
if (backButton.isMounted()) {
backButton.hide();
}
window.history.back();
});
}
console.log('TelegramProvider - init()');
if (miniApp.mountSync.isAvailable()) {
miniApp.mountSync();
}
if (closingBehavior.mount.isAvailable()) {
closingBehavior.mount();
closingBehavior.isMounted(); // true
}
if (closingBehavior.enableConfirmation.isAvailable()) {
closingBehavior.enableConfirmation();
closingBehavior.isConfirmationEnabled(); // true
}
} catch (err) {
console.error('Telegram SDK init failed:', err);
const cleanUrl = window.location.origin + window.location.pathname;
window.history.replaceState({}, '', cleanUrl);
}
return () => {
if (backButton.isMounted()) {
backButton.unmount();
}
};
}, []);
💬 6. Telegram всплывающие окна
Если вкратце, вы создаёте всплывающее окно с помощью метода popup.show
, указывая нужные кнопки.
Затем ждёте buttonId
, который возвращает popup.show
(то есть какую кнопку нажал пользователь), и выполняете действия в зависимости от выбранной кнопки.
import { popup } from '@telegram-apps/sdk-react';
export const showTelegramPopup = async (
title: string,
message: string,
buttonText: string[]
): Promise<boolean> => {
if (popup) {
const promise = popup.show({
title: title,
message: message,
buttons: buttonText.map((text, index) => ({
id: `button_${index}`,
type: 'default',
text: text,
})),
});
// popup.isOpened() -> true
const buttonId = await promise;
if (buttonId === 'button_0') {
return true;
// do something
} else if (buttonId === 'button_1') {
return false;
// do something else
}
// If buttonId is neither 'ok' nor 'cancel', return false by default
return false;
}
// If popup is not available, return false
return false;
};
🔗 Ссылки
Telegram Mini Apps SDK:
@telegram-apps/sdk-react и
[docs]
Telegram Bot API: https://api.telegram.org и docs с подробной инструкцией как его использовать
Мой пример Telegram Mini App
🔥 Анонс
Есть ещё много интересного — например, работа с платежами через Telegram Stars — но это не вошло в эту статью.
Если хотите, чтобы я осветила эту тему в следующий раз, поставьте лайк или оставьте комментарий ниже!