Telegram Mini Apps (formerly WebApps) let you create rich web applications that run directly within Telegram. They’re perfect for adding interactive features to your Telegram bot, from simple forms to complex interfaces. Let’s build one using React!
Prerequisites
- Node.js installed on your system
- Basic knowledge of React
- A Telegram account
- @BotFather access to create a bot
Creating Your Bot
- Message @BotFather on Telegram
- Use
/newbot
to create a new bot - Enable Mini Apps:
/mybots → Your Bot → Bot Settings → Menu Button → Configure Menu Button
- Save your bot token - you’ll need it later
Setting Up the React Project
Create a new React project using Vite and install the necessary dependencies:
npm create vite@latest telegram-mini-app -- --template react
cd telegram-mini-app
npm install @twa-dev/sdk
npm install
Initializing the Mini App
Create src/telegram.js
to handle Telegram-specific functionality:
import WebApp from '@twa-dev/sdk';
export const initTelegramApp = () => {
WebApp.enableClosingConfirmation();
WebApp.setHeaderColor('#2481cc');
WebApp.setBackgroundColor('#ffffff');
// Ready event
WebApp.ready();
};
export const getUserData = () => {
return WebApp.initDataUnsafe?.user || null;
};
export const sendDataToBot = (data) => {
WebApp.sendData(JSON.stringify(data));
};
export const closeApp = () => {
WebApp.close();
};
Building the React Interface
Update your App.jsx
with a basic interface:
import { useEffect, useState } from 'react';
import { initTelegramApp, getUserData, sendDataToBot, closeApp } from './telegram';
import './App.css';
function App() {
const [user, setUser] = useState(null);
const [message, setMessage] = useState('');
useEffect(() => {
initTelegramApp();
setUser(getUserData());
}, []);
const handleSubmit = (e) => {
e.preventDefault();
sendDataToBot({ message });
closeApp();
};
return (
<div className="app">
<header>
<h1>Mini App Demo</h1>
{user && <p>Welcome, {user.first_name}!</p>}
</header>
<main>
<form onSubmit={handleSubmit}>
<textarea
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="Enter your message..."
/>
<button type="submit">Send to Bot</button>
</form>
</main>
</div>
);
}
export default App;
Add some basic styling in App.css
:
.app {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
form {
display: flex;
flex-direction: column;
gap: 16px;
}
textarea {
padding: 12px;
border: 1px solid #ddd;
border-radius: 8px;
min-height: 100px;
}
button {
padding: 12px 24px;
background: #2481cc;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
}
button:hover {
background: #1a6dad;
}
Creating the Bot Backend
Create a new directory for your bot and initialize it:
mkdir telegram-bot
cd telegram-bot
npm init -y
npm install node-telegram-bot-api express cors
Create server.js
:
const TelegramBot = require('node-telegram-bot-api');
const express = require('express');
const cors = require('cors');
const token = 'YOUR_BOT_TOKEN';
const webAppUrl = 'YOUR_MINI_APP_URL'; // After deployment
const bot = new TelegramBot(token, { polling: true });
const app = express();
app.use(cors());
app.use(express.json());
// Handle /start command
bot.onText(/\/start/, (msg) => {
const chatId = msg.chat.id;
bot.sendMessage(chatId, 'Welcome! Try our Mini App:', {
reply_markup: {
keyboard: [[{
text: 'Open Mini App',
web_app: { url: webAppUrl }
}]],
resize_keyboard: true
}
});
});
// Handle Mini App data
bot.on('web_app_data', async (msg) => {
const chatId = msg.chat.id;
const data = JSON.parse(msg.web_app_data.data);
await bot.sendMessage(chatId, `Received: ${data.message}`);
});
// Start the server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Deployment
- Deploy your React app to a static hosting service (like Vercel or Netlify)
- Deploy your bot to a hosting service (like Heroku or DigitalOcean)
- Update
webAppUrl
in your bot code with the deployed Mini App URL - Update your bot’s menu button with the same URL through BotFather
Security Considerations
Always validate incoming data from Telegram. Here’s a validation helper:
const crypto = require('crypto');
function validateTelegramData(initData, botToken) {
const secret = crypto
.createHmac('sha256', 'WebAppData')
.update(botToken)
.digest();
const data = Object.fromEntries(new URLSearchParams(initData));
const checkString = Object.keys(data)
.filter(key => key !== 'hash')
.sort()
.map(key => `${key}=${data[key]}`)
.join('\n');
const hash = crypto
.createHmac('sha256', secret)
.update(checkString)
.digest('hex');
return hash === data.hash;
}
Testing Your Mini App
- Start a chat with your bot
- Click the “Open Mini App” button
- Enter a message and submit
- Verify that your bot receives and responds to the message
Best Practices
- Performance: Keep your bundle size small and optimize images
- Error Handling: Implement proper error boundaries and user feedback
- UI/UX: Follow Telegram’s design guidelines for a native feel
- Security: Always validate incoming data and use HTTPS
- State Management: Use React Context for complex state if needed
Conclusion
You now have a working Telegram Mini App integrated with a bot! This foundation can be extended to create more complex applications like games, forms, or interactive tools. Check the official documentation for more features and capabilities.