I recently built and launched WhisprMe — an anonymous messaging app that runs entirely inside Telegram as a Mini App. No app store, no downloads, just a link.
Here are 5 things that genuinely surprised me during development and after launch.
1. Telegram Stars Payments Are Absurdly Simple
I expected payments to be the hardest part. Credit card integrations, Stripe webhooks, PCI compliance nightmares…
Nope. Telegram Stars took about 30 lines of backend code:
// Create invoice
const link = await bot.telegram.createInvoiceLink({
title: 'Unlock Anonymous Message',
description: 'See who sent you this message',
payload: JSON.stringify({ userId, messageId }),
currency: 'XTR',
prices: [{ label: 'Unlock', amount: 1 }]
});
// Handle pre-checkout
bot.on('pre_checkout_query', (ctx) => {
ctx.answerPreCheckoutQuery(true);
});
// Handle successful payment
bot.on('message', (ctx) => {
if (ctx.message.successful_payment) {
const { userId, messageId } = JSON.parse(
ctx.message.successful_payment.invoice_payload
);
// Unlock the message in DB
}
});
That's it. Users tap "Pay 1 ⭐", confirm, done. No credit card forms. The conversion rate is significantly higher than traditional payment flows because there's zero friction.
2. Haptic Feedback Changes Everything
Adding this one line transformed how the app feels:
window.Telegram.WebApp.HapticFeedback.notificationOccurred('success');
I added haptic feedback on:
- Message sent ✅
- Message unlocked 🔓
- Achievement earned 🏆
- Button taps
Users never mentioned it explicitly, but engagement metrics went up after I added it. The app just feels native — like it belongs on the phone, not in a browser.
3. initData Is Your Auth Layer (But Validate It Server-Side!)
Telegram sends initData with every Mini App launch. It contains the user's ID, first name, username, etc. — cryptographically signed.
// Server-side validation
const crypto = require('crypto');
function validateInitData(initData, botToken) {
const params = new URLSearchParams(initData);
const hash = params.get('hash');
params.delete('hash');
const dataCheckString = [...params.entries()]
.sort(([a], [b]) => a.localeCompare(b))
.map(([k, v]) => `${k}=${v}`)
.join('\n');
const secretKey = crypto
.createHmac('sha256', 'WebAppData')
.update(botToken)
.digest();
const calculatedHash = crypto
.createHmac('sha256', secretKey)
.update(dataCheckString)
.digest('hex');
return calculatedHash === hash;
}
The surprise: I initially skipped server-side validation during development. Big mistake. Anyone can send fake initData from a browser console. Always validate the HMAC signature.
4. The Cold Start Problem Is Real
Building the app took 2 weeks. Getting the first 10 users took longer.
What worked:
-
Shareable links — each user gets
whisprme.app/u/usernamethat they can share on Instagram Stories, Telegram bio, etc. - Gamification — leaderboards and achievements gave people a reason to come back
- Referral system — invite friends, get bonus messages
What didn't work:
- Posting on Reddit (got auto-moderated everywhere)
- Cold DMs (felt spammy, stopped after 2)
The social virality loop is key: someone receives an anonymous message → they're curious → they share their own link → their friends send messages → repeat.
5. A $5/month VPS Handles More Than You Think
My entire stack runs on a single Hetzner VPS:
- Node.js/Express backend with PM2 cluster mode
- PostgreSQL database
- React frontend (static build served by Express)
- Nginx reverse proxy with SSL
Total cost: ~$5/month. For the first 1000 users, this is more than enough. I was tempted to over-engineer with Kubernetes, Redis, separate microservices... but a monolith on a VPS just works.
# My entire deployment:
pm2 restart all
That's the whole CI/CD. 🤷
The Stack
For anyone curious:
- Backend: Node.js, Express, Telegraf (bot framework)
- Database: PostgreSQL with raw SQL (no ORM)
- Frontend: React with vanilla CSS
- Payments: Telegram Stars
- Hosting: Hetzner VPS, PM2, Nginx
- i18n: Custom solution supporting English + Russian
Try It
If you want to see a real-world Telegram Mini App in action:
Share your link with friends, receive anonymous messages, and see the Stars payment flow in action. I'd love your technical feedback!
What's your experience with Telegram Mini Apps? Have you built one? What surprised you? Let me know in the comments!
Top comments (1)
Since writing this, I've extracted the auth and payment code into a standalone starter kit:
🔗 telegram-miniapp-starter
Includes
initDatavalidation (HMAC-SHA256), Stars payment flow, Express middleware, and React frontend hooks — everything mentioned in the article, ready to clone and use.Also wrote a detailed step-by-step for the Stars payment part specifically: How to Accept Payments in a Telegram Mini App Using Stars