Building SpyClub: A Complete Guide to Modern Telegram Mini App Development

Introduction
Telegram Mini Apps have emerged as a powerful platform for building engaging blockchain-enabled experiences. SpyClub represents a perfect fusion of casual gaming, social features, and blockchain technology, all wrapped in an accessible package that runs right inside Telegram.
This comprehensive guide will walk you through how we built SpyClub, offering practical insights for developers looking to create their own Telegram Mini Apps with blockchain integration.
Game Overview & Features
SpyClub reimagines the classic word association board game Codename for the Web3 era. Players join real-time matches where they compete to guess words based on clues. Best players then win $SPY tokens, which can be converted to USDC rewards.
Key Features:
- Real-time multiplayer games every 30 minutes
- Reward system combining in-game currency and real cryptocurrency ($SpyCoin on Hedera blockchain)
- Social features including referrals, leaderboards and Telegram bot messages
- Automated on-chain wallet creation and management
- Farming mechanism for passive earnings
- Progressive quest system for engagement
Technical Architecture

Tech Stack Breakdown
Frontend Stack
- Core: React with Vite and TypeScript
- State Management: Zustand for lightweight global state
- Styling: Tailwind CSS with shadcn/ui components
- Animations: Framer Motion for smooth transitions
- Real-time: Supabase Realtime for multiplayer features
- Platform Integration: Telegram Mini App SDK
- Deployment: CI/CD with Github + Vercel
Backend Stack
- Server: Fastify for high-performance API handling
- Database: Supabase (PostgreSQL) for data persistence
- Real-time: Supabase Realtime for WebSocket management
- Storage: Supabase Storage for media files
- Type Safety: TypeScript throughout the stack
External Integrations
Telegram Integration
- User authentication via Telegram
- Mini App SDK for native features (haptic feedback for instance)
- Telegraf as Bot API framework for notifications and updates
Have a look to our Github, we have created a boilerplate to kickstart your Telegram Mini App with React and Vite.
Blockchain Integration
- Hedera blockchain for token transactions
- Daily USDC rewards distribution with CRON jobs
- Automated on-chain wallet creation for users
Analytics & Monitoring
- User behavior tracking with MixPanel
- Performance monitoring with Google App Engine
- Error tracking and reporting with Sentry
Development Deep Dive
Game Room Management: The Heart of Multiplayer
Game rooms in SpyClub are dynamic entities that handle player interactions, scoring, and game state management. Here's a peek at our room management system:
export class GameRoom {
private players: Map<string, Player> = new Map()
private currentRound: Round | null = null
private scoreTracker: ScoreTracker
async startGame() {
if (this.players.size < MIN_PLAYERS) {
throw new Error('Not enough players')
}
this.currentRound = await this.initializeRound()
this.broadcastGameStart()
this.gameLoop = setInterval(() => {
this.updateGameState()
}, TICK_RATE)
}
private async updateGameState() {
if (this.shouldEndRound()) {
await this.endRound()
if (this.isGameComplete()) {
await this.endGame()
} else {
await this.startNextRound()
}
}
}
}
State Management: Keeping Everything in Sync
Frontend state management is crucial for a smooth gaming experience. Here's how we structure our Zustand game store:
interface GameState {
room: GameRoom | null
currentRound: RoundData | null
players: Player[]
userScore: number
leaderboard: LeaderboardEntry[]
}
const useGameStore = create<GameState>((set) => ({
room: null,
currentRound: null,
players: [],
userScore: 0,
leaderboard: [],
updateGameState: (newState: Partial<GameState>) =>
set((state) => ({ ...state, ...newState })),
handleRoundEnd: async (roundResults) => {
set((state) => ({
...state,
userScore: state.userScore + roundResults.score,
leaderboard: roundResults.newLeaderboard
}))
}
}))
Telegram Bot Setup
Let us guide through the process of creating a basic Telegram bot with custom commands. First, you need to chat with BotFather, Telegram's official bot for creating other bots. Here's how:
- Open Telegram and search for "@BotFather"
- Start a conversation with /newbot
- Follow the prompts to:
- Set your bot's display name
- Choose a unique username (must end in 'bot')
Once complete, BotFather will provide you with a Bot Token - this is your key to accessing Telegram's API! Keep it secure as we'll need it in our environment variables:
// From config.ts export const BOT_TOKEN = process.env.BOT_TOKEN || "" export const TELEGRAM_API_BASE_URL = "https://api.telegram.org"
Then, you can setup the bot command on the server:
import { FastifyInstance } from "fastify"
import { Telegraf, Context } from "telegraf"
import { BOT_TOKEN, BACKEND_URL, APP_URL, TELEGRAM_BOT_URL } from "../config"
export function setupBotCommands(fastify: FastifyInstance) {
const bot = new Telegraf(BOT_TOKEN)
bot.command("start", async (ctx: Context) => {
/** Your start command logic **/
})
// Set up webhook
fastify.post(`/bot${BOT_TOKEN}`, (request, reply) => {
bot.handleUpdate(request.body as any, reply.raw)
})
// Start the bot
bot.launch({
webhook: {
domain: `${BACKEND_URL}`,
hookPath: `/bot${BOT_TOKEN}`,
},
})
fastify.log.info("Bot commands set up successfully")
}
Finally, don't forget to register your webhook using Telegram bot API:
curl --location --request POST 'https://api.telegram.org/bot{bot_token}/setWebhook' payload_data = { ‘url’: your-webhook-url }
You can verify if your webhook was correctly set by calling:
curl --location 'https://api.telegram.org/bot{bot_token}/getWebhookInfo'
Deployment & Scaling: Ready for Growth
SpyClub's architecture is designed to scale horizontally thanks to Google App Engine capabilities.
- Game rooms are distributed across multiple server instances
- Database queries are optimized with proper indexing
- Caching layers for frequently accessed data
- Load balancing for even distribution of player connections
Our app.yaml looks like this:
runtime: nodejs20
service: spyclub-backend-prod
automatic_scaling:
min_instances: 1
inbound_services:
- warmup
env_variables: your env here
Lessons Learned
Throughout the development of SpyClub, we gained valuable insights:
- Real-time Consistency: Maintaining game state across multiple clients requires careful synchronization
- Blockchain Integration: Always implement retry mechanisms and proper error handling for transactions
- User Experience: The balance between game mechanics and blockchain features is crucial
- Performance: Optimize for mobile devices since most players use Telegram on phones
Ready to Build Your Own?
Creating a successful Telegram Mini App requires careful planning and execution. Whether you're building a game, a DeFi application, or something entirely new, the architecture and patterns we've shared can serve as a solid foundation.
Remember: The key to success is not just in the technical implementation, but in creating an engaging experience that keeps users coming back for more. Happy building!
Need help building your next blockchain project? Let's connect and turn your vision into reality!