Telegram Mini App demonstrating native TMA capabilities. Built by Unibrix to showcase expertise in Telegram Mini App development.
Stack: React 18 · TypeScript · Vite · Zustand · @tma.js/sdk-react · Telegram UI
| Page | TMA Feature | Description |
|---|---|---|
| Wallet | biometry |
Biometric-protected crypto price list (Face ID / Fingerprint) |
| Weather | locationManager |
Location-based weather using device geolocation |
| Photos | qrScanner |
QR scanner and photo gallery with camera access |
| Settings | cloudStorage |
User profile, preferences, cloud storage demo |
npm install
npm run devOpen http://localhost:5173/ — the app runs with a mock Telegram environment.
Some TMA features require a real device and HTTPS:
| Feature | Localhost | Real Device + HTTPS |
|---|---|---|
locationManager |
Limited | Full |
biometry |
No | Yes |
qrScanner |
No | Yes |
| Theme/haptics | Mock | Native |
1. One-time setup
brew install ngrok
ngrok config add-authtoken YOUR_TOKEN # from ngrok.com/dashboard2. Run
npm run dev:tunnelThis starts Vite + ngrok and auto-updates your bot's menu URL.
3. Test
Open your bot in Telegram on your phone — all features work!
Open @unibrix_demo_bot and click the menu button.
1. Configure base path
Edit vite.config.ts with your repo name:
// github.com/YourUsername/your-repo → '/your-repo/'
base: command === 'serve' ? '/' : '/tg-public-app/',2. Enable GitHub Pages
Go to repo Settings → Pages → Source: GitHub Actions
3. Push to main
The GitHub Action builds and deploys automatically on every push.
1. Create a bot
Open @BotFather and send /newbot. Save the token.
2. Configure environment
cp .env.example .env.productionEdit .env.production:
BOT_TOKEN=your_token_from_botfather
VITE_APP_URL=https://yourusername.github.io/your-repo/
3. Run setup script
./scripts/setup-bot.sh4. Test it
Open your bot in Telegram — click the menu button to launch the app!
| Feature | Description |
|---|---|
initData |
User info (name, username, photo, premium status) |
themeParams |
Auto dark/light theme from Telegram |
hapticFeedback |
Vibration feedback |
backButton |
Native back navigation |
mainButton |
Bottom action button |
popup |
Native alert dialogs |
cloudStorage |
Persist data across sessions |
biometry |
Face ID / Fingerprint authentication |
locationManager |
Device geolocation |
qrScanner |
QR code scanning |
src/
├── components/
│ ├── App.tsx # Router + theme setup
│ ├── TabBar/ # Bottom tab navigation
│ ├── Page.tsx # Page wrapper
│ └── Root.tsx # Error boundary wrapper
├── pages/
│ ├── WalletPage/ # Biometric protected list
│ ├── WeatherPage/ # Location-based weather
│ ├── PhotosPage/ # QR scanner + gallery
│ └── SettingsPage/ # User settings
├── store/ # Zustand state management
├── navigation/
│ └── routes.tsx # Route definitions
├── init.ts # SDK initialization
└── mockEnv.ts # Mock for local development
Environment files (gitignored):
.env.development— loaded bynpm run dev.env.production— loaded bynpm run build
Variables with VITE_ prefix are embedded at build time:
const url = import.meta.env.VITE_APP_URLMIT