← Guides
Playbook In Build products intermediate · 38 min read · Updated Apr 22, 2026
Part of the series Zero to revenue · Part 1

Ship a Telegram Mini App in 48 hours

A practical, end-to-end walkthrough — from BotFather to deploy — for shipping your first Telegram Mini App with auth, payments, and a real distribution plan.

Mini Apps are the closest thing the mobile web has to an App Store moment. They are HTML5 apps that run inside Telegram with native chrome, deep auth into the user’s identity, and a payments rail that takes minutes — not weeks — to wire up.

This guide takes you from zero to a deployed, paying-customers-ready Mini App in two days.

What is a Telegram Mini App?

A Mini App is a web page that Telegram embeds inside its own chrome. Your code is plain HTML/JS — React, Vue, vanilla, anything that runs in a browser. Telegram injects a JavaScript bridge (window.Telegram.WebApp) that gives you:

  • Identity: a signed payload (initData) you verify server-side to know who the user is.
  • Theme: the user’s current Telegram theme tokens, so your UI matches dark/light.
  • Native UI primitives: MainButton, BackButton, haptics, scanner, share link.
  • Payments: invoice flow that charges in Stars (digital goods) or fiat (physical).

The official surface is the Bot API, which exposes Mini Apps via web_app buttons. The full spec lives at core.telegram.org core.telegram.org/bots/webapps .

User device Telegram client WebView window.Telegram.WebApp initData (signed) themeParams Mini App (frontend) React / Vue / etc. Cloudflare / Vercel HTTPS only Your backend verify initData issue session JWT handle payments Bot API api.telegram.org
The five moving parts you'll wire together — only the frontend ships to Cloudflare/Vercel; the rest is handled by Telegram or your existing backend.

Prerequisites

  • A Telegram account (a real one, not a virtual number).
  • A laptop with Node 20+ (or Bun 1.1+).
  • A domain or a free subdomain on Cloudflare/Vercel/Fly. Mini Apps must be served over HTTPS.
  • 30 minutes for setup, then ~10 hours of actual coding spread across 2 days.
01

Create your bot with BotFather

Open Telegram, search @BotFather, send /newbot. Pick a display name and a _bot-suffixed username. Save the HTTP API token it gives you — you’ll need it server-side.

Then attach a Mini App:

/newapp                 → choose your bot
Title:                  Telegram Bible Demo
Description:            Build on Telegram, fast.
Photo:                  upload 640×360 PNG
GIF:                    optional
Web App URL:            https://your-app.example.com
Short name:             demo

Your Mini App is now reachable at t.me/your_bot/demo and via inline keyboard buttons.

core.telegram.org BotFather reference
02

Bootstrap the frontend

Use Vite + React (or your stack of choice). Install the Telegram SDK:

npm create vite@latest mini-app -- --template react-ts
cd mini-app
npm install @telegram-apps/sdk-react

In main.tsx, initialize the bridge:

import { init, miniApp, viewport } from "@telegram-apps/sdk-react";

init();
miniApp.mount();
viewport.mount();
miniApp.ready();

Calling miniApp.ready() tells Telegram your app has finished loading — Telegram hides its own loader and reveals your UI.

03

Authenticate the user, properly

Telegram passes a signed initData string to your Mini App. Never trust it client-side. Send it to your backend and verify the HMAC.

// server/auth.ts
import crypto from "node:crypto";

export function verifyInitData(initData: string, botToken: string): boolean {
  const params = new URLSearchParams(initData);
  const hash = params.get("hash")!;
  params.delete("hash");

  const dataCheck = [...params.entries()]
    .sort(([a], [b]) => a.localeCompare(b))
    .map(([k, v]) => `${k}=${v}`)
    .join("\n");

  const secret = crypto
    .createHmac("sha256", "WebAppData")
    .update(botToken)
    .digest();

  const computed = crypto
    .createHmac("sha256", secret)
    .update(dataCheck)
    .digest("hex");

  return computed === hash;
}

Once verified, parse initData.user — that’s your trusted user object: { id, first_name, username, language_code }. Mint your own session JWT from it.

core.telegram.org Validating initData
04

Charge with Stars in two API calls

Stars are Telegram’s in-app currency for digital goods. They are perfect for: unlocking premium features, tipping, paid templates, AI credits.

On your backend, create an invoice link via the Bot API:

const res = await fetch(`https://api.telegram.org/bot${TOKEN}/createInvoiceLink`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    title: "Pro plan",
    description: "Unlock the full guide library",
    payload: `user_${userId}_pro_2026_04`,
    currency: "XTR",                 // Stars
    prices: [{ label: "Pro", amount: 250 }],   // 250 Stars
  }),
});
const { result: invoiceUrl } = await res.json();

Hand invoiceUrl to the client and call:

import { openInvoice } from "@telegram-apps/sdk-react";
const status = await openInvoice(invoiceUrl);
// "paid" | "cancelled" | "failed" | "pending"

Then handle pre_checkout_query and successful_payment updates server-side to grant entitlement.

05

Deploy and distribute

Push your frontend to Cloudflare Pages or Vercel — both give you HTTPS for free. Update the URL in BotFather. That’s it for hosting.

For distribution:

  • Direct link: t.me/your_bot/demo works in any browser, opens Telegram if installed.
  • Start parameter: t.me/your_bot/demo?startapp=ref_alex — read it in initData.start_param to do referral tracking.
  • Inline mode: users can @your_bot in any chat to share your app.
  • Channels: drop a message with a Mini App button in your channel.
  • Stories: link Mini Apps from Telegram Stories — surprisingly high CTR.

Common gotchas

  • initData empty in browser dev tools — that’s expected. Telegram only injects it inside the Telegram client. Use a tunnel, not localhost.
  • Theme flicker — read themeParams once on mount and apply via CSS variables. Subscribe to themeChanged for runtime switches.
  • Viewport jump on iOS — call viewport.expand() early; some keyboards otherwise compress your app.
  • Stars refunds — fully manual. Plan a /refund admin command from day one.

Next steps

  • Add Cloud Storage (window.Telegram.WebApp.CloudStorage) for cross-device persistence without your own DB.
  • Add a referral leaderboard using Stars-paid badges.
  • Submit to the Telegram App Center once live (currently invite-only — apply via @BotSupport).

You shipped. Now grow.

Stay in the loop

One short email when something useful ships. No tracking pixels, no upsell.