Skip to main content
For the complete documentation index, see llms.txt. A full-text snapshot is also available at llms-full.txt.

TON AppKit Starter

A starter template for building applications with the TON AppKit

TON AppKit Starter is a Telegram Mini App starter kit built with TON AppKit, React, TypeScript, and Vite. Covers main AppKit features: wallet connection, balance monitoring, and TON transfers.

Runs on testnet by default. Switch to mainnet by changing NETWORK in src/utils/constants.ts.

01

02


Features

  • ๐Ÿ’Ž Connect/disconnect TON wallet via TON Connect
  • ๐Ÿ“Š Real-time balance monitoring with polling
  • ๐Ÿ“ค Send TON to any address with optional comment
  • ๐Ÿ”— Transaction confirmation with Tonscan explorer link
  • ๐Ÿ“ฑ Telegram Mini App ready โ€” theme sync, viewport expand, safe area support
  • ๐Ÿ‘ค Telegram user info โ€” name
  • ๐ŸŒ— Light/dark mode โ€” syncs with Telegram theme, falls back to system preference
  • ๐ŸŒ Works in a regular browser too

Prerequisites


Setup

1. Clone the repository

https://github.com/thisonedev/vault.git

2. Enter ton-appkit-starter directory

cd ton-appkit-starter

3. Install dependencies

npm install

4. Configure environment

cp .env.example .env

Open .env and fill in your values:

# Optional but recommended โ€” avoids rate limit errors
TONCENTER_API_KEY=<your_api_key_here>

# Your app's TON Connect manifest URL
# The demo manifest below works fine for local development
MANIFEST_URL=https://tonconnect-sdk-demo-dapp.vercel.app/tonconnect-manifest.json

Running an app

npm run dev

Open http://localhost:5173 in your browser.


Running as a Telegram Mini App

Telegram requires a public HTTPS URL to load a Mini App. During development, use ngrok to tunnel your local dev server.

1. Start your dev server

npm run dev

2. In a separate terminal, start ngrok

npx ngrok http 5173

Copy the https:// URL ngrok gives you, e.g. https://abc123.ngrok-free.app

3. Create a Telegram bot

  • Open @BotFather on Telegram
  • Send /newbot and follow the prompts โ€” pick a name and username
  • BotFather gives you a bot token โ€” save it for later

4. Set the Mini App URL

  • Send /mybots to BotFather
  • Select your bot โ†’ Bot Settings โ†’ Menu Button โ†’ Configure menu button
  • Paste your ngrok URL

5. Open the Mini App

  • Open your bot in Telegram
  • Tap the Menu button (bottom left, next to the message input)
  • Your app loads as a Mini App

Your app hot-reloads automatically on code changes โ€” no need to restart ngrok or reconfigure BotFather unless the ngrok URL changes.

Note: Free ngrok generates a new URL every time you restart it. To keep a stable URL during development, keep ngrok running or use a paid plan with a fixed domain.

Production: Deploy to any static host (Vercel, Netlify, Cloudflare Pages) and set that URL in BotFather instead.


Project Structure

ton-appkit-starter/
โ”œโ”€โ”€ index.html                        # Entry point โ€” includes Telegram WebApp script
โ”œโ”€โ”€ vite.config.ts                    # Vite config with Buffer polyfill and @ alias
โ”œโ”€โ”€ tsconfig.json                     # Root TypeScript config with project references
โ”œโ”€โ”€ tsconfig.app.json                 # TypeScript config for src/
โ”œโ”€โ”€ package.json                      # Dependencies and scripts
โ”œโ”€โ”€ .env.example                      # Environment variable template
โ”œโ”€โ”€ .gitignore                        # Ignored files โ€” node_modules, .env, dist
โ”œโ”€โ”€ eslint.config.js                  # ESLint config
โ”œโ”€โ”€ README.md                         # Project documentation
โ”‚
โ””โ”€โ”€ src/
    โ”œโ”€โ”€ main.tsx                      # React entry โ€” mounts app
    โ”œโ”€โ”€ App.tsx                       # Root โ€” AppKit, QueryClient, and provider setup
    โ”œโ”€โ”€ index.css                     # Telegram design tokens, Tailwind, global styles
    โ”œโ”€โ”€ polyfills.ts                  # Buffer polyfill required by @ton/core
    โ”‚
    โ”œโ”€โ”€ components/
    โ”‚   โ”œโ”€โ”€ shared/                   # Reusable UI primitives
    โ”‚   โ”‚   โ”œโ”€โ”€ Card.tsx              # Rounded surface container
    โ”‚   โ”‚   โ”œโ”€โ”€ CardRow.tsx           # Label/value row with optional divider
    โ”‚   โ”‚   โ”œโ”€โ”€ FormField.tsx         # Input with error message
    โ”‚   โ”‚   โ””โ”€โ”€ SectionTitle.tsx      # Section label above cards
    โ”‚   โ”‚
    โ”‚   โ”œโ”€โ”€ telegram/                 # Telegram-specific components
    โ”‚   โ”‚   โ””โ”€โ”€ TelegramProvider.tsx  # SDK init, theme sync, user/colorScheme context
    โ”‚   โ”‚
    โ”‚   โ”œโ”€โ”€ transfer/                 # Send flow
    โ”‚   โ”‚   โ”œโ”€โ”€ SendTon.tsx           # Transfer form using SendTonButton
    โ”‚   โ”‚   โ””โ”€โ”€ TransactionStatus.tsx # Success/error toast with Tonscan link
    โ”‚   โ”‚
    โ”‚   โ””โ”€โ”€ wallet/                   # Wallet state and display
    โ”‚       โ”œโ”€โ”€ Balance.tsx           # TON balance with polling
    โ”‚       โ”œโ”€โ”€ WalletConnect.tsx     # Connect/disconnect button
    โ”‚       โ””โ”€โ”€ WalletInfo.tsx        # Address, network badge, explorer link
    โ”‚
    โ”œโ”€โ”€ hooks/
    โ”‚   โ””โ”€โ”€ useIsConnected.ts         # Returns true if a wallet is connected
    โ”‚
    โ”œโ”€โ”€ types/
    โ”‚   โ”œโ”€โ”€ index.ts                  # Shared TypeScript interfaces
    โ”‚   โ””โ”€โ”€ telegram.d.ts             # Global type declarations for window.Telegram.WebApp
    โ”‚
    โ””โ”€โ”€ utils/
        โ”œโ”€โ”€ constants.ts              # Global constants โ€” network, URLs, intervals
        โ””โ”€โ”€ ton.ts                    # Helper functions โ€” formatting, validation, API

Components

TelegramProvider

Initialises the Telegram Mini App SDK and syncs Telegram's theme to CSS variables. Wraps the entire app so any component can access the Telegram context via useTelegram().

  • Calls tg.expand() to make the app full screen
  • Calls tg.ready() to hide the native loading indicator
  • Listens to themeChanged events and updates CSS variables in real time
  • Exposes isTMA, colorScheme, isReady, and user via context
import { useTelegram } from '@/components/TelegramProvider';

const { isTMA, colorScheme, isReady, user } = useTelegram();

// Show Telegram username
<p>Welcome, {user?.first_name ?? 'anon'}</p>

WalletConnect

Connect/disconnect button. Shows a connect button when no wallet is connected, and a connected state with a shortened address and disconnect option when a wallet is connected.

Uses useTonConnectUI from @tonconnect/ui-react to open the TON Connect modal.


WalletInfo

Displays wallet details after connection:

  • Wallet app name (e.g. Tonkeeper, MyTonWallet)
  • Network badge โ€” Testnet (yellow) or Mainnet (green), read from wallet.account.chain
  • Full address with tap-to-copy
  • Link to the wallet on Tonscan

Only rendered when a wallet is connected.


Balance

Displays the connected wallet's TON balance. Polls every BALANCE_POLL_INTERVAL_MS (10 seconds by default) to keep the value fresh.

  • Shows a skeleton loader while fetching
  • Shows the balance formatted to 2โ€“4 decimal places
  • Shows a retry button on error

Uses useBalance() from @ton/appkit-react.


SendTon

A transfer form with three fields: recipient address, amount (TON), and an optional comment. Uses SendTonButton from @ton/appkit-react which handles the wallet interaction internally.

  • Validates the recipient address format and amount before sending
  • Disables the button while a transaction is pending
  • Passes success/error results to TransactionStatus

Only rendered when a wallet is connected.


TransactionStatus

A toast notification shown after a send attempt.

  • Success: shows "Transaction sent" and polls the TonCenter API every 2 seconds (up to 10 attempts / 20 seconds) until it finds the transaction hash, then shows a direct Tonscan link
  • Error: shows a human-readable error message (e.g. "Transaction cancelled" instead of the raw SDK error)
  • Auto-dismisses after 12 seconds on success, 8 seconds on error
  • Can be manually dismissed with the โœ• button

Switching to Mainnet

Change the following values in src/utils/constants.ts:

export const NETWORK = Network.mainnet();
export const TONCENTER_BASE_URL = 'https://toncenter.com';
export const TONSCAN_BASE_URL = 'https://tonscan.org';

And update your .env:

TONCENTER_API_KEY=<your_mainnet_key>

Tech Stack

PackagePurpose
@ton/appkit-reactAppKit React hooks and components
@tonconnect/ui-reactTON Connect wallet hooks
@tanstack/react-queryData fetching and caching
tailwindcssUtility-first CSS
bufferNode.js Buffer polyfill for the browser

Resources