Telegram SaaS Framework

A framework for building production-ready Telegram bots in one evening

Telegram SaaS Base is a private framework I use to launch my own Telegram products. 28+ ready-made modules, built-in multi-tenancy, 5 payment providers, AI integration, and Web Mini App support in a single codebase.

t.me/Nabery1000BalivBot
Telegram SaaS Framework — bot architecture and multi-tenant infrastructure
12,000 players in the first month
28+ modules out of the box
3 minutes to your first bot
12 000
players launched @Nabery1000BalivBot in the first month, zero paid ads
28 +
ready modules: gamification, payments, AI, notifications, media
5
payment providers: Stripe, LiqPay, Monobank, Telegram Stars, CryptoMerchant
3 min
from a new bot token to a running bot in production
40 +
Prisma models in a single typed schema
17
security measures: JWT, HMAC-SHA256, RBAC, rate-limit, audit log

About the project

Telegram SaaS Base is a private personal framework I built to launch my own Telegram products quickly. Every time I need a new bot, I don’t start from scratch: I create a token, register the bot in the admin panel, select the required modules, configure them through the UI and set the webhook. The first bot with payments, localization and analytics takes about three minutes.

The framework is built on Next.js 16 with App Router, React 19, PostgreSQL 16, Redis 7, BullMQ for queues and grammY for the Telegram Bot API. All code is typed with TypeScript. The architecture follows vertical slices: each module is isolated and owns its route handlers, database schema, admin panel UI components and message handlers. Adding a new module requires no changes to the core.

The same codebase operates simultaneously in two modes: as a native Telegram Bot with commands, inline keyboards and callbacks, and as a Telegram Web Mini App with a full React interface. The admin panel manages all bots from a single point and supports multi-tenancy via AsyncLocalStorage with no direct tenant_id queries anywhere in the business logic.

Architecture

Core framework capabilities

Unified Dispatcher

A single entry point for everything: Telegram Bot API, Next.js HTTP routes and Web Mini App. One middleware stack, one authorization system, one source of truth for sessions and tenant context.

  • Telegram webhook, polling and HTTP API are handled by a single pipeline
  • Middleware executes once regardless of runtime (bot or web)
  • Tenant and user context is injected automatically via AsyncLocalStorage
  • Modules don't know which runtime they run in: one logic, different transports

Module Registry

Modules register automatically via a static registry on import. Connecting a new module is one line in the bot manifest. Removing it is the same line deleted. The framework core never changes when modules are added.

Multi-tenancy

Each bot is a separate tenant. AsyncLocalStorage holds the tenant context for the lifetime of a request. All business logic code is written without tenant_id: it is available automatically anywhere in the stack via ModuleContext.

Decorator-based routing

Command and callback routing via TypeScript decorators with Reflect Metadata. No manual handler registration, no switch-case on message text.

  • @BotCommand('/start') registers the command in the bot automatically
  • @CallbackQuery('action:*') supports wildcard pattern matching on callback data
  • @BotAction() handles text messages with string or RegExp patterns
  • Decorators stack: one method can respond to multiple triggers simultaneously

Payment layer

Strategy Pattern over 5 providers: Stripe, LiqPay, Monobank, Telegram Stars, CryptoMerchant. A new provider is added by implementing a single interface with no changes to module code.

AI integration

Two providers out of the box: OpenAI and Google Gemini. Any new AI provider takes 2 lines via a unified adapter. Full response typing, retry logic, rate-limit handling.

Telegram + Web Mini App

The same codebase serves the native bot with commands and inline keyboards and a full React Web Mini App. Mode switching without duplicating business logic.

AI localization

Translate the entire bot into any language in one click from the admin panel. AI generates translations, a human reviews. Supports any number of locales.

Stack

Technology stack

6 layers from the React UI to infrastructure. Each layer chosen for a specific purpose.

Frontend technologies

Frontend

Telegram Bot technologies

Bot Framework

Backend technologies

Backend

Payments and integrations

Payments & AI

Infrastructure

Infrastructure

Unified Dispatcher: one pipeline for the bot and the web

The central architectural challenge of the framework is this: a Telegram Bot runs via webhook or polling, receiving Update objects from the Telegram API — a server process with its own event loop. A Web Mini App runs via browser HTTP requests — standard Next.js routing. The admin panel makes REST calls to the API. These are three fundamentally different transport layers with different request-response models, different authorization systems and different data formats.

The naive approach is three separate code paths, with duplicated business logic or a separate abstraction layer per transport. Telegram SaaS Base solves this differently: a single Dispatcher — the Adapter pattern — normalizes all incoming events to a unified internal format. Telegram Update, HTTP Request and WebSocket messages pass through one middleware stack before reaching the module’s business logic. This stack sets the tenant context via AsyncLocalStorage, checks authorization, resolves the user and writes to the audit log. All of this happens once, regardless of transport.

The consequence: modules are written with no transport awareness. The same payment processing method works whether it is called via a Telegram command or via the Web Mini App. No duplication, no if (isTelegram) in business code.

Routing

@BotCommand, @CallbackQuery, @BotAction

Command and callback routing via TypeScript decorators with Reflect Metadata. A method with a decorator is registered in the bot on module import. No manual event subscription, no switch-case on message text.

@BotCommand declares the command and description for /help automatically
@CallbackQuery supports wildcards: 'payment:*' matches any suffix
@BotAction accepts a string or RegExp for matching text messages
Decorators stack: one method responds to multiple triggers simultaneously
TypeScript
@Module('referral')
class ReferralModule extends BaseModule {

  @BotCommand('/referral', 'Referral program')
  async handleReferral(ctx: BotContext): Promise<void> {
    const user = ModuleContext.getUser();
    const stats = await this.referralService.getStats(user.id);
    await ctx.reply(this.i18n.t('referral.stats', stats));
  }

  @CallbackQuery('referral:share')
  async handleShare(ctx: BotContext): Promise<void> {
    await ctx.answerCallbackQuery();
    await ctx.reply(this.referralService.buildShareLink());
  }

  @BotAction(/^referral_code_(.+)$/)
  async handleCode(ctx: BotContext): Promise<void> {
    const code = ctx.match[1];
    await this.referralService.applyCode(
      ModuleContext.getUser().id,
      code
    );
  }
}

Vertical slices: a module as a self-contained unit

Module architecture in Telegram SaaS Base follows the Vertical Slice pattern: each module contains everything it needs to operate. Not a service layer with shared repositories, not horizontal slicing by file type — a vertical slice from bot handlers through the database schema to admin panel UI components.

The module structure is fixed: handlers/ with decorated methods, services/ with business logic, schema.prisma with the database schema, admin/ with React components and admin API routes, i18n/ with translations, index.ts as entry point. When setting up a new bot, modules are connected via the manifest in one line. Database schemas are merged automatically by a merge script, then a single Prisma migration is run.

A practical consequence for development: when working on a specific module, you open one directory and see everything — handlers, logic, schema, UI. No need to jump between controllers/, services/, repositories/, models/ in different parts of the tree. This is especially valuable when moving or removing a module: it moves as a single package.

Schema Merge

Modular database schema

Each module has its own schema.prisma file. Before migration a merge script joins all schemas into one, then a single migration runs. Tables from different modules don't share names: each table is prefixed by the module name.

Module schema lives alongside the code, not in a shared file
Remove a module: delete the directory, remove from manifest, run migration
Prisma client is fully typed: all models accessible via a single PrismaClient
Prisma
// modules/referral/schema.prisma
model ReferralCode {
  id         String   @id @default(cuid())
  botId      String
  code       String   @unique
  ownerId    String
  usageCount Int      @default(0)
  reward     Int      @default(0)
  createdAt  DateTime @default(now())

  bot        Bot           @relation(fields: [botId], references: [id])
  usages     ReferralUsage[]
}

model ReferralUsage {
  id         String   @id @default(cuid())
  codeId     String
  userId     String
  createdAt  DateTime @default(now())

  code       ReferralCode @relation(fields: [codeId], references: [id])
}

// After merge: npx prisma migrate dev

Onboarding

A new bot in 3 minutes

1

Create a bot in @BotFather

30 seconds

Send /newbot to @BotFather, choose a name and username. Receive the API token.

2

Add the bot in the admin panel

30 seconds

Paste the token into the registration form. The framework automatically pulls the bot name and avatar from the Telegram API.

3

Select and enable modules

1 minute

The UI shows all available modules with descriptions. A checkbox activates a module for this bot. Database schemas are merged automatically.

4

Configure modules

30 seconds

Each active module exposes a configuration form: texts, limits, payment keys, toggles. All through the UI without editing code.

5

Set the webhook

10 seconds

Click 'Set Webhook' in the admin panel. The framework registers the endpoint with Telegram and returns a confirmation status.

6

Bot in production

Done

The bot responds to commands, accepts payments and renders the Web Mini App. All data is collected in the admin panel in real time.

Multi-tenancy: one framework, many bots

When the framework serves multiple bots simultaneously, the classic multi-tenant problem arises: how to guarantee data isolation between tenants without business logic ever knowing multi-tenancy exists. Adding WHERE bot_id = $1 to every SQL query is not a solution — it is a source of bugs.

In Telegram SaaS Base, multi-tenancy is implemented via Node.js AsyncLocalStorage. When the Dispatcher receives an incoming request it identifies the tenant (bot) by token or request header, loads the tenant configuration and stores it in the AsyncLocalStorage store for the duration of the request. Any code within that request — module business logic, Payment Service, AI adapter — retrieves the tenant context via ModuleContext.getTenant() without any explicit argument.

The result: modules are written with no awareness of multi-tenancy. The referral service calculates stats — it simply works with data from the current tenant. The payment module selects a provider — from the current tenant’s configuration. No passing tenantId through call chains, no data leaks between bots. AsyncLocalStorage guarantees isolation at the event-loop level, even with parallel requests inside a single Node.js process.

Integrations

Payment providers

International bank cards, Apple Pay, Google Pay. Subscription model support, webhook processing, automatic retry on failures. The best fit for products with a global audience.

  • Checkout Sessions and Payment Intents via Stripe API v2024
  • Webhook signature verification, idempotency keys
  • Full transaction audit log in PostgreSQL

Ukrainian payment provider: Visa/Mastercard, Google Pay, Apple Pay, cash-in terminals. Optimum for Ukrainian audiences with low transaction fees.

  • LiqPay API v3: invoice creation, status check, callback
  • HMAC-SHA1 webhook signature verification

Payment service from Ukraine's Monobank. Integration via the monopay API: creating payment links, tracking status callbacks.

  • Invoice creation, redirect URL, webhook callback

Telegram's native payment system. Users buy Stars inside the app and use them to pay for bot services without leaving to a browser. Conversion rates are higher than external payment pages.

  • sendInvoice API, pre_checkout_query handler, successful_payment handler
  • Native UX without redirects outside Telegram

Accepting cryptocurrency payments via the CryptoMerchant API. Creating payment addresses, tracking confirmations, webhook on transaction completion.

  • Multiple cryptocurrencies through a single adapter

AI integration: two providers out of the box, any new one in two lines

The framework ships with two AI providers: OpenAI (GPT-4o, GPT-4-Turbo and all models via a single API) and Google Gemini (Gemini 1.5 Pro and Flash). Both providers implement a common IAIProvider interface with complete(), chat() and embed() methods. A module that needs AI retrieves the provider via ModuleContext.getAI() — the tenant selects the provider in settings, while the module code has no dependency on any specific AI.

Adding a new provider means implementing the IAIProvider interface and registering the class in the factory. This takes roughly two lines in the configuration file. No changes to modules already using AI. Strategy Pattern in its pure form: the algorithm (provider) is swapped without changing the context (module).

The most impactful practical feature is AI-driven bot translation. The admin panel collects all localization strings from all active modules, sends them to AI with a system prompt to preserve formatting, receives translations and saves them to the database. The administrator reviews the result in a table and edits manually if needed. The entire bot is translated into a new language in a single request with no deployment.

Security

17 security measures

JWT RS256
Admin API authentication with key rotation
admin + super_admin
HMAC-SHA256
Signature verification for all incoming webhook requests
Telegram + providers
RBAC
Role system: super_admin, admin, viewer with granular permissions
per-route middleware
Rate Limit
Redis-based request throttling at the user and IP level
per-user, per-IP
Audit Log
Full log of all admin actions with IP and user-agent
PostgreSQL + indexes
Zod
Strict validation of all incoming API data and bot commands
runtime type safety

Localization: i18n as a first-class citizen

Every module in the framework contains an i18n/ directory with translation files in JSON format. Translation keys are typed: TypeScript knows all available localization keys for a module, autocomplete works in the IDE, and errors in keys are caught at compile time. On startup the application loads translations from all active modules and merges them into a single namespace partitioned by module name.

Calling a translation in code: this.i18n.t('referral.invite_text', { count: stats.referrals }). No magic strings, no runtime errors from missing keys. Supports interpolation, pluralization and nested keys. Language is resolved from the tenant’s settings, or from the Telegram user’s language preferences where needed.

AI translation is integrated into the admin panel: one button collects all strings from active modules, sends them to AI and saves the results. The entire bot is translated in a single request. A diff mechanism translates only the added or changed strings when modules are updated.

Infrastructure

Services and their roles

Data layer

PostgreSQL 16

Primary store

40+ typed Prisma models, transactions, indexes on key fields. Each module contributes its own schema fragment via the merge script.

Cache & queues

Redis 7 + BullMQ

Cache and workers

Session storage, rate limiting at the user and IP level, deferred and retryable jobs via BullMQ workers. Separate worker processes do not block the main event loop.

Application

Next.js 16 (App Router)

HTTP server

HTTP API with all routes, server-side rendering for the React admin panel and Web Mini App. App Router provides Server Components, streaming and edge runtime where needed.

Bot Layer

grammY

Telegram runtime

Incoming Update processing via webhook or polling. The grammY middleware stack is integrated with the Dispatcher: one pipeline for authorization, tenant context and routing to decorated module handlers.

Files

S3-compatible storage

Object storage

User media files, data exported via the admin panel and database backups. The provider abstraction allows switching between AWS S3, MinIO or any S3-compatible service with no code changes.

Orchestration

Docker Compose

Single stack

Five services (app, worker, worker2, db, redis) defined in a single compose file. One docker compose up command brings up the full environment with hot reload for development or the production stack with proper resource limits.

Core

Core subsystems

Module Registry

Singleton registry of all system modules. Automatically discovers modules on import via static registration. Provides access to module metadata: name, dependencies, active commands.

EventBus

Observer Pattern for cross-module communication. Modules publish events (payment.completed, user.registered) and subscribe to events from other modules without direct dependencies between them.

ModuleContext

Facade Pattern: a single access point to framework services inside a module. Through ModuleContext a module retrieves the current user, tenant, AI provider, payment service and i18n.

TenantContext

AsyncLocalStorage store for tenant context during a request. Guarantees data isolation between bots even under parallel requests in a single Node.js process.

CommandBus (BullMQ)

Command Pattern on top of BullMQ. Deferred jobs, retry with backoff, prioritization, cron scheduler. Separate workers offload the main process.

FSM Scenes

Finite state machine for multi-step user dialogs. State is stored in Redis between messages. Scenes are attached to modules with a decorator. Timeout and cancellation event support.

Need a Telegram bot or architecture consultation?

I design and launch Telegram products on my own framework. If you are interested in this stack or need help with bot architecture, write to me. Let's discuss the task without obligation.

I will respond within 24 hours.