Помните, как все носились с PWA? Теперь такая же история происходит с Telegram Mini Apps (TMA) — веб-приложениями внутри мессенджера. Разработчики делают на них всё: от простых утилит до полноценных магазинов с оплатой в криптовалюте. Расскажем, как создать своё первое мини-приложение и не сойти с ума.
Что такое Telegram Mini Apps и почему в Telegram о них все говорят
TMA — это веб-приложения, которые живут внутри Telegram. По сути, это обычные сайты на HTML, CSS и JavaScript, но с доступом к крутым фишкам самого мессенджера. Например, можно использовать данные пользователя или встроенные платежи.
Чем они хороши:
- Не нужно проходить модерацию App Store или Google Play
- Пользователям не надо ничего устанавливать — всё работает прямо в Telegram
- Можно использовать любимый стек: хоть React, хоть Vue, хоть чистый JavaScript
- Есть доступ к 900+ миллионам пользователей Telegram
Примеры успешных TMA
Давайте посмотрим на реальные примеры, чтобы понять, что можно сделать:
- Wallet — кошелёк для TON с функцией покупки никнеймов
- Hamster Kombat — известная тапалка, которая набрала 250 миллионов пользователей
- DurgerKing — шуточный клон известной сети фастфуда
С чего начать разработку
Для создания TMA вам понадобится:
- Редактор кода. VS Code или WebStorm — без разницы
- Базовые знания HTML, CSS и JavaScript
- Telegram на телефоне и компьютере
- Желание разобраться в новой теме
Шаг 1: Создаём бота-помощника
Первым делом нужно создать бота — он будет стартовой точкой для вашего приложения. Это проще, чем кажется:
- Найдите @BotFather в Telegram
- Отправьте ему команду `/newbot`
- Придумайте имя для бота
- Сохраните токен, который пришлёт BotFather — он пригодится для работы с API
Бот может не только запускать ваше приложение, но и обрабатывать команды пользователей.
Например:
«`javascript
// Пример простого бота на Node.js с использованием библиотеки node-telegram-bot-api
const TelegramBot = require(‘node-telegram-bot-api’);
const bot = new TelegramBot(token, {polling: true});
bot.onText(/\/start/, (msg) => {
const chatId = msg.chat.id;
bot.sendMessage(chatId, ‘Привет! Нажми на кнопку, чтобы открыть приложение’, {
reply_markup: {
inline_keyboard: [[
{
text: ‘Открыть приложение’,
web_app: {url: ‘https://ваш-домен.com/app’}
}
]]
}
});
});
«`
Шаг 2: Готовим рабочее окружение
Создадим базовую структуру проекта:
«`
my-tma/
├── index.html
├── styles/
│ └── main.css
├── scripts/
│ └── app.js
└── assets/
└── images/
«`
Минимальный `index.html`:
«`html
<!DOCTYPE html>
<html>
<head>
<meta charset=»UTF-8″>
<meta name=»viewport» content=»width=device-width, initial-scale=1.0″>
<title>Моё первое TMA</title>
<link rel=»stylesheet» href=»styles/main.css»>
<script src=»https://telegram.org/js/telegram-web-app.js»></script>
</head>
<body>
<div id=»app»>
<h1>Привет, Telegram!</h1>
</div>
<script src=»scripts/app.js»></script>
</body>
</html>
«`
Шаг 3: Пишем само приложение
Теперь самое интересное. Вот пример простого приложения-счётчика с сохранением данных:
// app.js
const app = {
data: {
count: 0
},
init() {
// Инициализация приложения
this.setupTheme();
this.setupCounter();
this.setupMainButton();
},
setupTheme() {
// Применяем тему Telegram
const theme = window.Telegram.WebApp.themeParams;
document.body.style.backgroundColor = theme.bg_color;
document.body.style.color = theme.text_color;
},
setupCounter() {
// Создаём счётчик
const counter = document.createElement(‘div’);
counter.innerHTML = `
<h2>Счётчик: <span id=»count»>0</span></h2>
<button id=»increment»>+1</button>
<button id=»decrement»>-1</button>
`;
document.querySelector(‘#app’).appendChild(counter);
// Добавляем обработчики
document.querySelector(‘#increment’).onclick = () => this.updateCount(1);
document.querySelector(‘#decrement’).onclick = () => this.updateCount(-1);
},
setupMainButton() {
// Настраиваем главную кнопку
const MainButton = window.Telegram.WebApp.MainButton;
MainButton.setText(‘Сохранить’);
MainButton.onClick(() => this.saveData());
MainButton.show();
},
updateCount(delta) {
this.data.count += delta;
document.querySelector(‘#count’).textContent = this.data.count;
},
saveData() {
// Отправляем данные боту
window.Telegram.WebApp.sendData(JSON.stringify(this.data));
}
};
// Запускаем приложение
window.Telegram.WebApp.ready();
app.init();
Стилизация приложения
Важно, чтобы ваше приложение выглядело нативно в Telegram.
Вот базовые стили:
«`css
/* main.css */
body {
margin: 0;
padding: 16px;
font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, Roboto, Helvetica, Arial, sans-serif;
}
#app {
max-width: 600px;
margin: 0 auto;
}
button {
background: var(—tg-theme-button-color, #3390ec);
color: var(—tg-theme-button-text-color, #ffffff);
border: none;
border-radius: 8px;
padding: 8px 16px;
margin: 4px;
cursor: pointer;
}
button:hover {
opacity: 0.9;
}
«`
Расширяем функционал
Работа с данными пользователя
Telegram предоставляет базовую информацию о пользователе:
«`javascript
const user = window.Telegram.WebApp.initDataUnsafe.user;
if (user) {
console.log(`Привет, ${user.first_name}!`);
// Доступны также: last_name, username, language_code и др.
}
«`
Добавляем платежи через TON
Если хотите принимать платежи, можно интегрировать TON Connect:
«`javascript
import { TonConnectUI } from ‘@tonconnect/ui’;
const tonConnectUI = new TonConnectUI({
manifestUrl: ‘https://your-app.com/tonconnect-manifest.json’,
buttonRootId: ‘connect-wallet’
});
// Создаём транзакцию
async function sendTransaction() {
const transaction = {
validUntil: Date.now() + 1000000,
messages: [
{
address: ‘EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N’,
amount: ‘10000000’, // 0.01 TON
}
]
};
try {
const result = await tonConnectUI.sendTransaction(transaction);
console.log(‘Транзакция отправлена:’, result);
} catch (error) {
console.error(‘Ошибка:’, error);
}
}
«`
Как тестировать
Для локальной разработки рекомендую использовать:
- Local HTTPS — можно настроить через `mkcert` или использовать сервисы вроде `ngrok`
- Тестовый сервер Telegram — чтобы не спамить реальных пользователей
- DevTools в браузере — для отладки
Пример настройки HTTPS локально:
«`bash
# Установка mkcert
brew install mkcert # для macOS
mkcert -install
mkcert localhost
# Запуск сервера с HTTPS
npx serve —ssl-cert localhost.pem —ssl-key localhost-key.pem
«`
Частые грабли
1. Проблемы с загрузкой
Распространённая ошибка — тяжёлые приложения. Вот что поможет:
«`javascript
// Ленивая загрузка изображений
const images = document.querySelectorAll(‘img[data-src]’);
const imageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
imageObserver.unobserve(img);
}
});
});
images.forEach(img => imageObserver.observe(img));
«`
2. Проблемы с вёрсткой
Используйте CSS-переменные Telegram для адаптивности:
«`css
:root {
—tg-viewport-height: 100vh;
—tg-viewport-stable-height: 100vh;
}
.app-container {
min-height: var(—tg-viewport-stable-height);
padding-bottom: var(—tg-viewport-height, 0px);
}
«`
3. Непонятный UI
Следуйте принципам Telegram при разработке интерфейса:
— Используйте системные шрифты
— Поддерживайте тёмную тему
— Делайте крупные тачзоны (минимум 44×44 пикселя)
Что дальше?
Когда базовая версия готова:
- Залейте код на хостинг с HTTPS
- Добавьте URL приложения через @BotFather
- Протестируйте в реальных условиях
- Соберите фидбек от пользователей
Продвижение приложения
- Добавьте приложение в каталог @miniapps — это официальный каталог TMA
- Расскажите о нём в Telegram-каналах разработчиков
- Создайте свой канал для обновлений и поддержки
- Собирайте метрики использования через Google Analytics или свою систему
От простого к сложному
Начните с малого — сделайте простое приложение, которое решает одну конкретную задачу. Потом можно добавлять новые фичи:
— Интеграцию с TON для приёма платежей
— Сохранение данных на сервере
— Сложную логику и анимации
Вот пример простого приложения для начала — список задач:
«`javascript
const todoApp = {
tasks: [],
init() {
this.setupUI();
this.loadTasks();
},
setupUI() {
const form = document.createElement(‘form’);
form.innerHTML = `
<input type=»text» id=»new-task» placeholder=»Новая задача»>
<button type=»submit»>Добавить</button>
<ul id=»task-list»></ul>
`;
form.onsubmit = (e) => {
e.preventDefault();
this.addTask();
};
document.querySelector(‘#app’).appendChild(form);
},
addTask() {
const input = document.querySelector(‘#new-task’);
const task = input.value.trim();
if (task) {
this.tasks.push(task);
this.renderTasks();
input.value = »;
this.saveTasks();
}
},
renderTasks() {
const list = document.querySelector(‘#task-list’);
list.innerHTML = this.tasks
.map((task, index) => `
<li>
${task}
<button onclick=»todoApp.deleteTask(${index})»>✕</button>
</li>
`)
.join(»);
},
deleteTask(index) {
this.tasks.splice(index, 1);
this.renderTasks();
this.saveTasks();
},
saveTasks() {
// Отправляем данные боту
window.Telegram.WebApp.sendData(JSON.stringify({
type: ‘tasks’,
data: this.tasks
}));
},
loadTasks() {
// В реальном приложении здесь был бы запрос к серверу
this.tasks = [];
this.renderTasks();
}
};
todoApp.init();
«`
Полезные ссылки
— Официальная документация по Mini Apps