Telegram Mini Apps
Bookygram ships two Telegram Mini Apps. Both are React 19, TypeScript and Vite single-page apps that open inside Telegram from their own bot and talk only to the Bookygram API.
| Client app | Professional (master) app | |
|---|---|---|
| Workspace | apps/client_tg_app (bookygram-client-tg) | apps/master_tg_app (master-tg-app) |
| Who uses it | People booking appointments | Professionals running schedules, services and appointments |
| Bot | Client bot | Professional bot |
| Channel-auth app ID | client | professional |
| Dev server | http://127.0.0.1:4178 (fixed port) | http://localhost:5173, listening on all interfaces |
| Preview server | vite preview on 4178 | vite preview on 4173 |
| API access in development | Calls VITE_API_URL directly (default http://127.0.0.1:3000) | Same origin; the dev and preview servers proxy /auth and /professional to the API |
| Behavior | Telegram client Mini App | Telegram professional Mini App |
Connected mode and browser preview
Each app decides its mode once, when it starts:
- Connected — Telegram supplied raw signed launch data
(
Telegram.WebApp.initData). The app signs in through the API and shows only server data. See Mini App sign-in and Mini App OIDC flow. - Preview — there is no launch data, for example when the page is opened in
a normal browser. The app shows a labeled sample experience kept in
localStorage. It never signs in and never calls the API.
The client app loads the two modes as separate bundles
(src/ConnectedClientMiniApp.tsx and src/ClientMiniApp.tsx), so the sample
data and mock link resolver are never part of the connected bundle.
initDataUnsafe is used only for display hints such as the start parameter;
it never authenticates anyone.
Commands
Run these from the app's directory, after npm install at the repository root
and a build of packages/contracts:
| Command | Client app | Professional app |
|---|---|---|
npm run dev | Vite dev server on 127.0.0.1:4178 | Vite dev server on :5173 |
npm run build | tsc --noEmit && vite build | tsc --noEmit && vite build |
npm run preview | Serves dist/ on 127.0.0.1:4178 | Serves dist/ on :4173 |
npm test | Node tests in tests/ and Vitest in src/ | Vitest in src/ and Node tests in tests/ |
Telegram opens Mini Apps only from HTTPS URLs. For a phone, expose the dev or
preview server through an HTTPS tunnel. The client dev server allows ngrok
hostnames (.ngrok-free.app, .ngrok-free.dev, .ngrok.app, .ngrok.io);
the professional server allows any host.
Local bot launchers
Both apps include small Python launchers for testing a Mini App from a real
Telegram chat. They poll the bot with getUpdates, so they cannot run while
that bot's webhook points at the API — use a separate test bot or stop the
launcher first. See
Move Telegram webhooks to the API.
| Launcher | What it does |
|---|---|
client_tg_app/bot.py --url <https-url> | Sets the chat menu to the given Mini App URL and acknowledges messages. Reads TELEGRAM_BOT_TOKEN from client_tg_app/.env.local. Contact updates are acknowledged but never linked to an API account |
client_tg_app/preview_server.py | Serves the built dist/ on 127.0.0.1:4179 for a tunnel |
master_tg_app/bot/bot.py | Sets the Графік menu button and answers /start with an Open schedule button. Reads BOT_TOKEN and WEBAPP_URL from master_tg_app/.env |
master_tg_app/bot/run_preview.py --port 4175 | Builds the app, serves it, starts an ngrok tunnel on a fixed development domain, runs bot.py, and rebuilds and reloads open Mini Apps when source files change |
These launchers are for development only. They do not authenticate anyone and do not replace the API webhooks.
Source map
| Concern | Client app | Professional app |
|---|---|---|
| Entry and mode choice | src/main.tsx | src/main.tsx, src/App.tsx |
| Telegram SDK adapter | src/telegram.ts | src/telegram.ts |
| Session (sign-in, refresh, sign-out) | src/channelSession.ts | src/channelSession.ts |
| Business API client | src/clientApi.ts | src/professionalApi.ts |
| Server-backed state | src/connectedStore.ts | src/connectedStore.tsx |
| Sample preview data | src/mockApi.ts, src/account.ts | src/store.tsx |
The two channelSession.ts files implement the same session logic; the
professional copy only adds signOut to its token-source interface.
Related pages
- Mini App configuration — every environment variable both apps and the API need.
- Mini App OIDC flow — how Telegram launch data becomes a Supabase session.
- Channel authentication — the API slice behind sign-in, its endpoints and errors.