- 04 - Flows/Telegram Mini App.md: major expansion — TelegramSellerShopView, TelegramCartView, TelegramAccountView, useTelegramCart/useTelegramShops hooks, full nav model, SDK surface table, shop→cart→checkout handoff flow - 01 - Architecture/Frontend Architecture.md: add Telegram Mini App section, TON Connect dependency, update to v2.8.59 - 09 - Audits/Activity Log.md: new entry for frontend@9bafbbb (v2.8.57–2.8.59) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
32 KiB
title, tags, related_models, related_apis, task
| title | tags | related_models | related_apis | task | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Telegram Mini App Flow |
|
|
|
5.4 |
Last updated: 2026-06-03 Status: IN PROGRESS — Task 5.4 (dependencies: 5.1 auth infra, 5.2 Telegram sign-in endpoint) Frontend branch:
integrate-main-into-development· v2.8.59 Entry point:src/sections/telegram/· route/telegram
Telegram Mini App Flow
End-to-end specification for the Amaneh Telegram Mini App — a fully self-contained marketplace shell surfaced inside Telegram's in-app browser via the WebApp SDK. Buyers and sellers can browse requests, create new escrow requests, shop seller templates, manage a cart, review offer state, follow payments, and message each other without leaving Telegram.
1. Architecture Overview
Telegram Client
└─ Mini App iframe (https://amn.gg/telegram)
└─ TelegramMiniAppView ← shell orchestrator
├─ useTelegramLiveContext ← SDK probe + polling
├─ useTelegramLanguage ← EN / FA detection
├─ useTelegramAutoSignIn ← silent JWT exchange
├─ useTelegramMainButton ← native chrome sync
├─ useTelegramBackButton ← native chrome sync
├─ useTelegramHaptic ← haptic wrapper
├─ useTelegramCart ← shared localStorage cart
│
├─ [state: loading] → TelegramLoadingState
├─ [state: unsupported] → TelegramUnsupportedState
├─ [state: unlinked] → TelegramUnlinkedState
└─ [state: linked]
├─ TelegramHeader
├─ TelegramTabBar (Home / Shop / Requests / Chat / Account)
│
├─ TelegramHomeView
├─ TelegramShopView → TelegramSellerShopView
├─ TelegramRequestsView → TelegramRequestDetailView
├─ TelegramChatView → TelegramChatThreadView
├─ TelegramAccountView
└─ [overlay] TelegramNewRequestView
└─ [overlay] TelegramNotificationsView
└─ [overlay] TelegramCartView
The shell is a single-page, no-router design: all navigation (tabs, overlays, detail drilldowns) is pure React state in TelegramMiniAppView. window.location.assign is only used as a final escape hatch to the full web dashboard.
2. Launch Points
| Entry | Mechanism | startapp context |
|---|---|---|
| Bot profile | User opens bot → taps "Open App" | none |
| Menu button | Pinned button in any chat with the bot | none |
| Inline button | Bot sends a card with an embedded button | req_<requestId> |
| Direct deep link | https://t.me/AmanehBot/app?startapp=req_<id> |
req_<requestId> |
| Web fallback | Browser at /telegram |
none (unsupported state) |
startapp / tgWebAppStartParam is read from either the WebApp SDK (window.Telegram.WebApp) or from URL query/hash params (for older Telegram clients that append them directly).
3. SDK Initialisation & Context Probe
File: src/utils/telegram-webapp.ts · getTelegramContext()
The function assembles a TelegramContext object from:
window.Telegram.WebApp— primary SDK surface (available when the app is opened inside Telegram).- URL query/hash fallback —
tgWebAppStartParam,tgWebAppData,tgWebAppVersion,tgWebAppPlatform— used by older clients or during dev testing.
Fields extracted:
| Field | Source | Notes |
|---|---|---|
isMiniApp |
Any Telegram signal present | Drives unsupported vs unlinked state |
initData |
webApp.initData or tgWebAppData URL param |
HMAC-signed payload sent to /api/auth/telegram |
initDataUnsafe |
webApp.initDataUnsafe |
Client-side user identity (not trusted) |
safeArea |
contentSafeAreaInset or safe_area_insets |
Parsed to {top, right, bottom, left} in px |
theme |
webApp.themeParams |
Both camelCase and snake_case normalised |
platform |
webApp.platform or URL param |
e.g. ios, android, tdesktop |
startParam |
startapp / tgWebAppStartParam / start_param |
Deep-link context |
isUnsupported |
!webApp && Boolean(startParam) |
Partial signal — no SDK but has URL param |
Polling on mount (useTelegramLiveContext): Telegram sometimes finishes injecting the WebApp object after the first React render. The hook re-probes at 0 ms, 100 ms, 500 ms, and 1000 ms after mount, and also re-probes on hashchange events (triggered by the native back-button on some platforms).
4. Shell State Machine
getTelegramStatus(context, hasWebAccount) returns one of three states:
unsupported ─── !context.isMiniApp
(opened in browser, not Telegram)
unlinked ─────── isMiniApp && (!user || !telegramUser.id)
(inside Telegram but no JWT session linked)
linked ──────── isMiniApp && user && telegramUser.id
(authenticated, full shell rendered)
State transitions occur on:
- Auth session check completing (
loading → false) - Telegram auto sign-in completing (
tgAuthLoading → false) - Manual sign-in button tap (unlinked → linked)
5. Authentication Flow
5.1 Silent Auto Sign-In
Hook: useTelegramAutoSignIn · File: hooks/use-telegram-auto-sign-in.ts
On mount, if context.isMiniApp && context.initData && !user:
- Exchange
initDatafor a JWT by callingsignInWithTelegram({ initData })→POST /api/auth/telegram. - On success, call
checkUserSession()to refresh the auth context. - If the backend returns
isNewUser: true, showTelegramOnboardingSheet. - A
useRefdeduplication guard (attemptedInitDataRef) prevents re-runs under React Strict Mode's double-effect behaviour.
5.2 Manual Sign-In (Unlinked State)
When initData is present but auto sign-in failed (or hasn't run yet), TelegramUnlinkedState renders:
- Continue with Telegram — calls the same
signIn()function fromuseTelegramAutoSignIn. - Sign in with email —
window.location.assign(paths.auth.jwt.signIn). - Create an account —
window.location.assign(paths.auth.jwt.register).
When initData is absent (accessed via a path that skips Telegram context), only the email/register buttons appear.
5.3 Backend Endpoint
POST /api/auth/telegram — expects { initData: string }. Backend verifies the HMAC using the Telegram bot token, extracts user from the payload, upserts a User record (telegramId, telegramVerified: true), and issues a JWT + refresh token. Returns { token, refreshToken, isNewUser }.
6. Navigation Model
All navigation is in-shell React state — no Next.js router is involved.
activeTab : 'home' | 'shop' | 'requests' | 'chat' | 'account'
overlayScreen : 'new-request' | 'notifications' | 'cart' | null
openConversationId : string | null
openRequestId : string | null
openSellerId : string | null
Priority rendering (first match wins):
openConversationId→TelegramChatThreadViewopenRequestId→TelegramRequestDetailViewopenSellerId→TelegramSellerShopViewoverlayScreen === 'cart'→TelegramCartViewoverlayScreen === 'notifications'→TelegramNotificationsViewoverlayScreen === 'new-request'→TelegramNewRequestViewactiveTab→ appropriate tab view
Back button (Telegram native BackButton) dismisses in reverse priority order: chat thread → request detail → seller shop → overlay → returns to home tab.
BackButton visibility: shown whenever state === 'linked' and either an overlay/drilldown is active, or activeTab !== 'home'.
MainButton visibility: hidden while any overlay is open. When visible:
- Linked → "New Request" (opens
overlayScreen = 'new-request') - Unlinked → "Sign In" (navigates to the JWT sign-in page)
Both chrome buttons are styled with the amaneh saffron palette (color: #C2410C, text_color: #FFFFFF) via setParams (WebApp SDK >= 6.1).
7. Tab Structure
The shell has five bottom tabs rendered by TelegramTabBar:
| Tab | Icon | View | Purpose |
|---|---|---|---|
| Home | house | TelegramHomeView |
Welcome banner, quick-action cards, escrow-state chips |
| Shop | storefront | TelegramShopView |
Sellers list; drill into seller store; add templates to cart |
| Requests | list | TelegramRequestsView |
User's escrow requests with status stepper |
| Chat | speech bubble | TelegramChatView |
Conversation list + support entry |
| Account | person | TelegramAccountView |
Profile, preferences, links to web dashboard sections |
handleTabSelect clears all overlays and drill-down IDs before switching tab.
8. Supported Flows
8.1 Home Tab
TelegramHomeView is the landing screen shown on first open. It contains:
- Welcome banner (
TelegramWelcomeBanner): escrow account summary, primary CTA. - Quick-action cards (
TelegramQuickActions): shortcuts to Requests, Payments, Chat. - Escrow state chips (
TelegramEscrowStateChips): legend of status values visible in the platform.
8.2 Shop Tab — Sellers List
TelegramShopView (telegram-shop-view.tsx):
- Fetches all sellers via
useTelegramShops()→ SWR wrappinggetTemplateSellers()→GET /api/request-templates/sellers. - Renders
TelegramShopRowper seller: avatar, name, rating, template count, sales count. - Shows a floating cart badge button in the header when
totalItems > 0; tap opensoverlayScreen = 'cart'. - Tap a seller row → sets
openSellerId→ navigates toTelegramSellerShopView.
8.3 Shop Tab — Seller Store
TelegramSellerShopView (telegram-seller-shop-view.tsx):
- Fetches seller + active templates via
useTelegramSellerShop(sellerId)→GET /api/request-templates/sellers/:id. - Dark header: seller avatar, name, rating, template count, description.
- Each template card shows: image, title, 2-line description, budget range, usage count.
- Two actions per template:
- Add to cart / Remove from cart — toggles item in
useTelegramCart(localStorage, no API). Button is filled blue when not in cart, outline when added. - Order this template —
<a href>to/dashboard/request/from-template?shareableLink=.... Exits the Mini App to the web dashboard (single-template direct order, bypasses cart).
- Add to cart / Remove from cart — toggles item in
- Floating "Cart · N templates" sticky button at bottom when
totalItems > 0; tap callsonOpenCart().
8.4 Shopping Cart Overlay
TelegramCartView (telegram-cart-view.tsx):
- Rendered as
overlayScreen = 'cart'; dismissed by Telegram BackButton. - Lists each cart item: image, name, seller name, USDT price × quantity, +/− quantity controls, remove button.
- Subtotal/total in USDT, locale-formatted (
fa-IRfor Persian,en-USfor English); amounts alwaysdir="ltr". - "Continue to payment" — plain
<a href={paths.shops.checkout}>link; exits Mini App to web checkout.
Cart storage (useTelegramCart):
- Reads/writes
localStoragekeyapp-request-template-checkout— the same key the webRequestTemplateCheckoutProviderreads. This is the cart handoff mechanism: the cart built in Telegram IS the cart the web checkout page hydrates. - Dispatches a custom
tg-cart-changedDOM event on every write; listens on both that event and the nativestorageevent so all open tabs stay in sync. - Operations:
addTemplate(template, seller),removeItem(itemId),changeQuantity(itemId, qty),isInCart(templateId). - No API calls — cart is purely client-side until checkout.
- Cart item model:
id,templateId,name,description,price(fromtemplate.budget.min),quantity,image,sellerId,sellerName,category,shareableLink,deliveryInfo,maxUsage,usageCount,remainingCapacity.
8.5 Web Checkout Handoff
Destination: /dashboard/shops/checkout — RequestTemplateCheckoutView wrapped by RequestTemplateCheckoutProvider.
The provider reads the shared localStorage key and hydrates the TMA cart. The checkout is a 3-step stepper:
| Step | Component | Description |
|---|---|---|
| 0 (Cart review) | RequestTemplateCheckoutCart |
Item list, quantities, remove, totals, discount/shipping |
| 1 (Address) | RequestTemplateCheckoutBillingAddress |
Physical address or online delivery email |
| 2 (Payment) | RequestTemplateCheckoutPayment |
Wallet payment + socket confirmation |
| Complete | RequestTemplateCheckoutOrderComplete |
Confirmation dialog, cart reset |
Payment execution calls convertTemplatesToRequests() to create escrow records, then awaits a template-checkout-payment-confirmed socket event. A guard checks createdRequestIds is non-empty before advancing (prevents stray global socket events from triggering premature completion). Stock validation clamps or removes items exceeding remainingCapacity before payment.
8.6 Browse Requests (Requests Tab)
TelegramRequestsViewfetches the user's purchase requests viauseTelegramMyRequests(GET/api/requests).- Displays a skeleton loader, then a scrollable list of
TelegramRequestRowitems. - Each row shows: title, status chip, budget, creation date.
- Tap → sets
openRequestId→ rendersTelegramRequestDetailView.
8.7 Request Detail with Stepper
TelegramRequestDetailViewfetches a single request viauseTelegramRequest.- Renders
TelegramRequestStepper— a visual timeline of the escrow status flow frompending_payment→completed. determineCurrentStepFromStatusmaps the currentstatusto a step index.- Also renders: budget, description, creation date, category, urgency.
- Dates formatted via
toLocaleDateStringwithfa-IRlocale for Persian.
8.8 Create New Request
TelegramNewRequestViewis a full-screen overlay (not a routed page).- Form fields: title, description, category (fetched from
/api/categories), budget min/max, urgency. - On submit: calls
createPurchaseRequest()→ POST/api/purchase-requests. - On success: closes overlay, switches
activeTabto'requests'. MainButtonis hidden while the overlay is open (submit lives in the form itself).
8.9 Chat Tab
TelegramChatViewshows the user's active conversations viauseTelegramConversations.- Includes a Support row that calls
createSupportChat()→POST /api/chat/support, then opensTelegramChatThreadViewwith the returned conversation ID. - Tap a conversation row → sets
openConversationId→ rendersTelegramChatThreadView. TelegramChatThreadViewloads messages viauseTelegramChatThread, rendersTelegramChatBubbleitems, and includesTelegramChatComposerfor sending.- Optimistic send: message appears immediately, confirmed/rolled back on API response.
- Real-time updates via Socket.IO events; SWR is mutated on
new-notificationandunread-count-updateevents.
8.10 Account Tab
TelegramAccountView (telegram-account-view.tsx):
The account tab has four sections. All user data is passed as props from the shell (loaded via useAuthContext() — no fetch on mount).
Profile header:
- Avatar (from
user.profile.avatar, falls back to initials), full name, Telegram@username, role chip (buyer / seller / admin / resolver / guard). - Verification chips: "Telegram Verified" (if
user.telegramVerified) and "Email Verified" (ifuser.isEmailVerified).
Preferences section:
- Language toggle (FA / EN, in-shell via
TelegramLanguageToggle). - General Settings →
/dashboard/account(web, labeled "Opens in the web dashboard"). - Wallet → truncated address (
0x1234…abcd) or "not connected" →/dashboard/account/wallet(web). - Notifications → opens
TelegramNotificationsViewoverlay in-shell. - Addresses →
/dashboard/account/address(web). - Passkey →
/dashboard/account/passkey(web).
Help section:
- Support →
createSupportChat()→ opensTelegramChatThreadViewin-shell. - Terms & Conditions → placeholder, "coming soon".
Session section:
- Sign Out →
TelegramBottomSheetconfirmation dialog →authSignOut()+window.location.assign(paths.auth.jwt.signIn).
8.11 Notifications Overlay
TelegramNotificationsViewis rendered asoverlayScreen = 'notifications'.- Fetches via
useTelegramNotifications→getNotifications(userId, 1, 50)→GET /api/notifications?userId=...&page=1&limit=50. - Real-time updates: Socket.IO events
new-notification,unread-count-updatetrigger SWR mutate. - "Mark all read" calls
markAllNotificationsAsRead(userId)→PATCH /api/notifications/mark-all-read.
9. API Calls
| Action | Hook / call | Backend endpoint |
|---|---|---|
| Auto sign-in | useTelegramAutoSignIn → signInWithTelegram({initData}) |
POST /api/auth/telegram |
| Sellers list | useTelegramShops → getTemplateSellers() |
GET /api/request-templates/sellers |
| Seller + templates | useTelegramSellerShop → getSellerWithTemplates(id) |
GET /api/request-templates/sellers/:id |
| Marketplace sellers | useTelegramSellers → getSellers() |
GET /api/marketplace/sellers |
| My requests | useTelegramMyRequests |
GET /api/requests |
| Single request | useTelegramRequest |
GET /api/purchase-requests/:id |
| Create request | shell → createPurchaseRequest() |
POST /api/purchase-requests |
| Conversations | useTelegramConversations |
GET /api/chat/conversations |
| Chat thread | useTelegramChatThread |
GET /api/chat/:id + Socket.IO real-time |
| Support chat | createSupportChat() |
POST /api/chat/support |
| Notifications | useTelegramNotifications |
GET /api/notifications?userId=...&page=1&limit=50 |
| Mark all read | markAllNotificationsAsRead(userId) |
PATCH /api/notifications/mark-all-read |
| Auth sign-out | authSignOut() |
JWT sign-out endpoint |
Cart operations (add/remove/quantity) are pure localStorage — no API calls until web checkout.
10. Bilingual Support (EN / FA)
Language detection priority (useTelegramLanguage):
?lang=URL query param — dev preview override.localStoragekeyamn_tg_lang— user's persisted manual selection.initDataUnsafe.user.language_code— Telegram-reported language ("fa"or"fa-IR"→ Persian).- Fallback → English.
Language toggle: TelegramLanguageToggle in the header — two buttons [ EN | فا ]. On tap: haptic light + language switch + persist to localStorage.
RTL layout:
| Element | EN (LTR) | FA (RTL) |
|---|---|---|
Root dir attribute |
ltr |
rtl |
| Font family | IBM Plex Sans | Vazirmatn |
| Arrow icons | → |
← |
| Text alignment | left | right (inherits from dir) |
| Chip list wrap | left-to-right | right-to-left |
| Amounts | always dir="ltr" |
always dir="ltr" |
Font size bumps for Persian: body 13 px → 14 px, labels 10 px → 11 px (Vazirmatn renders optically smaller).
Translation structure:
// src/sections/telegram/locales/en.ts + fa.ts
const TR = {
en: { loading, unsupported, unlinked, header, home, shop, requests,
chat, account, newRequest, tabs, main, onboarding, errors, displayName, dir },
fa: { /* same keys, Farsi strings, dir: 'rtl' */ },
};
All JSX uses t.<section>.<key> — no inline strings in components.
11. Design System
File: src/sections/telegram/constants.ts · src/sections/telegram/telegram-shell-css.ts
The Mini App has a distinct visual identity (cream/saffron Persian palette) that does not inherit from the main dashboard theme. All tokens are feature-scoped.
Palette: TG_PALETTE
| Token | Hex | Usage |
|---|---|---|
cream50 |
#FBF6EB |
Page background |
ink900 |
#1C1410 |
Primary text |
ink600 |
#6B5D4E |
Secondary text / labels |
saffron600 |
#C2410C |
Primary action, MainButton |
saffron500 |
#D97757 |
Hover states |
pistachio700 |
#3D6B4F |
Success / released states |
pomegranate700 |
#8E2424 |
Error / disputed states |
bgPage |
#E7DFCB |
Shell outer background |
Fonts: TG_FONTS — Source Serif 4 (headings), IBM Plex Sans (body LTR), Vazirmatn (body RTL), IBM Plex Mono (amounts/addresses).
CSS: buildTelegramShellCss() injects a <style> tag at shell root with all class utilities (.tg-chip, .tg-shell, .tg-tab-bar, .tg-header, etc.). Theme CSS variables (--cream-50, --ink-900, etc.) are set on .tg-shell root.
Safe area: getTelegramSafeAreaStyle(safeArea) maps the Telegram-reported safe area insets to CSS padding using max(${px}px, env(safe-area-inset-*)) to handle both Telegram-native and iOS/Android safe areas.
12. Telegram SDK Usage Patterns
12.1 Safe-Area Inset
// TelegramContext.safeArea = { top, right, bottom, left } (px)
// Source: webApp.contentSafeAreaInset || webApp.safe_area_insets
// Normalised to number via parseNumber() — rejects non-finite strings
const topInset = (context.safeArea?.top ?? 0) as number;
All views receive topInset / bottomInset props and add them as explicit paddingTop / paddingBottom to avoid content being obscured by the Telegram chrome.
12.2 Haptic Feedback
// useTelegramHaptic(webApp) → haptic('light' | 'medium')
webApp?.HapticFeedback?.impactOccurred?.(type)
Used on: tab switches (light), new-request CTA (medium), language toggle (light), back button (light). All calls are wrapped in try/catch — the API may be absent on older clients.
12.3 Back Button
useTelegramBackButton({ webApp, isVisible, onClick })
// Calls webApp.BackButton.show() / hide() and registers onClick handler
// Cleanup: offClick() on unmount / visibility change
12.4 Main Button
useTelegramMainButton({ webApp, isReady, text, onClick })
// Calls webApp.MainButton.show() / hide(), setText(), setParams()
// Saffron palette: color: '#C2410C', text_color: '#FFFFFF'
// setParams requires WebApp >= 6.1; silent fallback for older clients
12.5 Theme Integration
Telegram's themeParams is normalised (both camelCase and snake_case accepted) and injected as CSS custom properties on the shell root (--telegram-shell-bg, --telegram-shell-text, etc.). The amaneh palette overrides these for the Mini App's own UI, but components can reference them for adaptive behaviours.
13. Edge Cases
| Scenario | Detection | Handling |
|---|---|---|
| Opened in browser (not Telegram) | context.isMiniApp === false |
TelegramUnsupportedState — shows "Open in Telegram" badge, web dashboard link |
| Partial Telegram signal (URL params but no SDK) | !webApp && Boolean(startParam) → isUnsupported: true |
Same unsupported state |
| Telegram SDK injected late | useTelegramLiveContext polls at 0/100/500/1000 ms |
Re-probes until SDK is ready; seed context bypasses polling |
initData absent (no auth data) |
!context.initData in unlinked state |
Sign-in button triggers error string t.errors.no_init_data; email/create buttons remain available |
| Auto sign-in replay (React Strict Mode) | attemptedInitDataRef.current === context.initData |
Deduplication ref — second effect is a no-op |
| Backend sign-in failure | Catch block in useTelegramAutoSignIn |
Error string displayed in TelegramUnlinkedState; retry via "Continue with Telegram" |
| New user first login | result.isNewUser === true |
TelegramOnboardingSheet shown over the shell; dismissed to account settings or "Later" |
| Expired session inside Mini App | Auth context user === null after session check |
Shell falls back to unlinked state |
| Old Telegram client (< 6.1) | setParams throws |
Try/catch silences it; button shows without saffron colour |
| RTL + keyboard overlap | Viewport shrinks on soft keyboard open | flex: 1 + overflowY: auto on content area; bottom safe-area inset on tab bar |
| Persian locale date formatting | lang === 'fa' |
toLocaleDateString('fa-IR', ...) in formatDate helper |
| Cart cross-tab sync | Multiple tabs / Mini App + web | tg-cart-changed DOM event + storage event both trigger re-render |
| Template at capacity | remainingCapacity === 0 at checkout |
Stock validation clamps/removes over-capacity items before payment |
| Stray global socket on checkout | template-checkout-payment-confirmed fires unexpectedly |
Guard checks createdRequestIds.length > 0 before advancing to completion step |
14. File Map
src/
app/telegram/page.tsx # Next.js route (thin shell, no auth guard)
utils/telegram-webapp.ts # SDK probe, context types, shell style helpers
sections/telegram/
constants.ts # TG_PALETTE, TG_FONTS, TG_EASE, status maps
telegram-shell-css.ts # buildTelegramShellCss() — inlined CSS blob
index.ts # barrel
locales/
types.ts # TelegramDict, TelegramLang, TelegramTabId
en.ts # English strings
fa.ts # Persian strings
index.ts # getTelegramDict(lang)
hooks/
use-telegram-live-context.ts # SDK polling
use-telegram-language.ts # EN/FA detection + ?lang= + localStorage persist
use-telegram-auto-sign-in.ts # initData → JWT exchange
use-telegram-main-button.ts # MainButton lifecycle
use-telegram-back-button.ts # BackButton lifecycle
use-telegram-haptic.ts # HapticFeedback wrapper
use-telegram-cart.ts # localStorage cart (shared with web checkout)
use-telegram-shops.ts # GET /api/request-templates/sellers
use-telegram-seller-shop.ts # GET /api/request-templates/sellers/:id
use-telegram-sellers.ts # GET /api/marketplace/sellers
use-telegram-my-requests.ts # GET /api/requests
use-telegram-request.ts # GET /api/purchase-requests/:id
use-telegram-conversations.ts # Chat conversation list
use-telegram-chat-thread.ts # Chat thread + optimistic send
use-telegram-notifications.ts # GET /api/notifications
index.ts
view/
telegram-mini-app-view.tsx # Shell orchestrator (all state lives here)
telegram-home-view.tsx # Home tab
telegram-shop-view.tsx # Shop tab — sellers list
telegram-seller-shop-view.tsx # Seller store drill-down + cart actions
telegram-cart-view.tsx # Cart overlay
telegram-requests-view.tsx # Requests list tab
telegram-request-detail-view.tsx # Request drilldown + stepper
telegram-new-request-view.tsx # New request overlay form
telegram-chat-view.tsx # Chat conversation list tab
telegram-chat-thread-view.tsx # Chat thread drilldown
telegram-account-view.tsx # Account + preferences + sign-out tab
telegram-notifications-view.tsx # Notifications overlay
index.ts
components/
telegram-header.tsx # AMN logo + subtitle + language toggle
telegram-tab-bar.tsx # Bottom tab bar (5 tabs)
telegram-welcome-banner.tsx # Home: escrow account banner + CTA
telegram-quick-actions.tsx # Home: action cards (Requests / Payments / Chat)
telegram-escrow-state-chips.tsx # Home: status chip legend
telegram-shop-row.tsx # Shop: seller list row
telegram-request-row.tsx # Requests: list row
telegram-request-stepper.tsx # Detail: visual escrow timeline
telegram-list-row.tsx # Generic list row primitive
telegram-list-skeleton.tsx # Skeleton loader for lists
telegram-chat-row.tsx # Chat: conversation list row
telegram-chat-bubble.tsx # Chat: message bubble
telegram-chat-composer.tsx # Chat: message input
telegram-loading-state.tsx # Loading spinner state
telegram-unlinked-state.tsx # Unlinked / sign-in prompt state
telegram-unsupported-state.tsx # Not-in-Telegram fallback state
telegram-onboarding-sheet.tsx # New-user onboarding bottom sheet
telegram-empty-state.tsx # Generic empty list state
telegram-language-toggle.tsx # EN | FA header toggle
telegram-bottom-sheet.tsx # Generic bottom sheet primitive
telegram-form-field.tsx # Form field + input style helper
telegram-seal-mark.tsx # SealMark logo component
telegram-icons.tsx # Telegram-scoped icon set
index.ts
15. Current Implementation Status (v2.8.59)
| Area | Status | Notes |
|---|---|---|
| Shell + state machine | Done | TelegramMiniAppView — all states wired |
| SDK probe + live context | Done | Polling + hashchange listener |
| Auto sign-in | Done | Deduped initData exchange |
| Manual sign-in (unlinked) | Done | Email + create account fallbacks |
| Bilingual EN/FA | Done | Full string inventory, RTL layout, Vazirmatn font |
| Language toggle | Done | Header toggle + localStorage persist |
?lang= dev preview param |
Done | URL param override added to useTelegramLanguage |
| Home tab | Done | Banner + quick actions + state chips |
| Shop tab — sellers list | Done | API-backed with skeleton + empty states, cart badge |
| Shop tab — seller store | Done | Templates list, add/remove cart, direct order link |
| Shopping cart (localStorage) | Done | Shared key with web checkout; cross-tab sync |
| Cart overlay | Done | Quantity controls, remove, total, checkout link |
| Web checkout handoff | Done | localStorage handoff; stock guard; socket guard |
| Requests list | Done | API-backed with skeleton + empty states |
| Request detail + stepper | Done | Status timeline, budget, dates with fa-IR locale |
| New request form | Done | In-shell overlay, category fetch, validation |
| Chat list | Done | API-backed conversation list + support row |
| Chat thread | Done | Messages + optimistic send + Socket.IO real-time |
| Account tab | Done | Profile, preferences, help, web-dashboard links, sign-out |
| Notifications overlay | Done | API-backed; Socket.IO real-time; mark-all-read |
| Telegram chrome (MainButton / BackButton) | Done | Saffron palette, lifecycle hooks |
| Haptic feedback | Done | All tap interactions |
| Safe area insets | Done | Normalised from SDK + CSS env() fallback |
Deep link startapp context |
Partial | Parsed but not yet used to auto-navigate to a request |
| Bilingual onboarding sheet | Done | Shown on isNewUser flag |
| Unsupported / browser fallback | Done | Web dashboard link |
Open Items
startappdeep link routing: ifcontext.startParammatchesreq_<id>, auto-openTelegramRequestDetailViewon first render.- Backend room-scoped Socket.IO for real-time chat updates (global socket event broadcast was fixed client-side in v2.8.4; server-side scoping is a follow-up).
16. Related Documents
- PRD - Telegram Mini App Bilingual (EN + FA) — bilingual string inventory and RTL layout spec
- PRD - Telegram Phone Number Authentication — phone-number auth as a future sign-in path
- Authentication Flow — JWT lifecycle shared with the Mini App auth
- Purchase Request Flow — escrow state machine surfaced in the stepper
- Chat Flow — real-time messaging that the Mini App embeds
- Request Template Checkout — web checkout flow that the Mini App cart hands off to