> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Telegram Mini App

![](https://mintcdn.com/dynamic-docs/Mu-tjFQVUvR9RrdN/images/telegram/telegram-mini-app.jpg?fit=max\&auto=format\&n=Mu-tjFQVUvR9RrdN\&q=85\&s=1ae10631193bd99df01dd6a2c7b98e1e)

## Introduction

Telegram Mini Apps (or TMAs) are web applications that run inside the Telegram messenger.

Dynamic works out of the box with TMAs. Scaffold your app and add the Dynamic JavaScript SDK by following the quickstart guide.

> [!NOTE]
>
> This recipe uses the Dynamic JavaScript SDK (`@dynamic-labs-sdk/client` + `@dynamic-labs-sdk/evm`, plus `@dynamic-labs-sdk/react-hooks` if you read state with hooks). See the [JavaScript Quickstart](https://docs.dynamic.xyz/docs/javascript/reference/quickstart.md) or [React Quickstart](https://docs.dynamic.xyz/docs/javascript/reference/react-quickstart.md) for the base setup.

> [!TIP]
>
> You can see a live example of a Dynamic integration in a TMA when using [Flooz](https://t.me/flooz_xyz).

## Integration guide

To get started, use one of the TMA templates outlined [here](https://docs.telegram-mini-apps.com/packages/telegram-apps-create-mini-app).

The basic command to scaffold a new TMA is:

```bash theme={"system"}
npx @telegram-apps/create-mini-app@latest
```

Install the Dynamic JavaScript SDK. Add `@dynamic-labs-sdk/react-hooks` and its TanStack Query peer dependency only if you plan to read state with React hooks:

```bash theme={"system"}
npm install @dynamic-labs-sdk/client @dynamic-labs-sdk/evm @dynamic-labs-sdk/react-hooks @tanstack/react-query
```

Create a singleton client module. Importing this file at app root registers extensions before any component renders:

```ts src/lib/dynamicClient.ts theme={"system"}
import { createDynamicClient, initializeClient } from "@dynamic-labs-sdk/client";
import { addEvmExtension } from "@dynamic-labs-sdk/evm";

export const dynamicClient = createDynamicClient({
  autoInitialize: false,
  environmentId: import.meta.env.VITE_DYNAMIC_ENV_ID as string,
  metadata: {
    name: "My Telegram Mini App",
    universalLink: window.location.origin,
  },
});

addEvmExtension();
void initializeClient();
```

If you plan to read state with `@dynamic-labs-sdk/react-hooks`, wrap your routes with `QueryClientProvider` (outer) and `DynamicProvider` (inner) in `src/components/Root.tsx`:

> [tab] Before
>
> ```tsx theme={"system"}
> <AppRoot
>     appearance={miniApp.isDark ? 'dark' : 'light'}
>     platform={['macos', 'ios'].includes(lp.platform) ? 'ios' : 'base'}
> >
>     <Router location={location} navigator={reactNavigator}>
>         <Routes>
>             {routes.map((route) => <Route key={route.path} {...route} />)}
>             <Route path='*' element={<Navigate to='/'/>}/>
>         </Routes>
>     </Router>
> </AppRoot>
> ```

> [tab] After
>
> ```tsx theme={"system"}
> import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
> import { DynamicProvider } from '@dynamic-labs-sdk/react-hooks';
> import { dynamicClient } from '@/lib/dynamicClient';
>
> const queryClient = new QueryClient();
>
> <AppRoot
>     appearance={miniApp.isDark ? 'dark' : 'light'}
>     platform={['macos', 'ios'].includes(lp.platform) ? 'ios' : 'base'}
> >
>     <QueryClientProvider client={queryClient}>
>         <DynamicProvider client={dynamicClient}>
>             <Router location={location} navigator={reactNavigator}>
>                 <Routes>
>                     {routes.map((route) => <Route key={route.path} {...route} />)}
>                     <Route path='*' element={<Navigate to='/'/>}/>
>                 </Routes>
>             </Router>
>         </DynamicProvider>
>     </QueryClientProvider>
> </AppRoot>
> ```

That's it. The JavaScript SDK is headless (there is no `DynamicWidget`). How you read auth and wallet state depends on whether you call client functions directly or use React hooks:

> [tab] JavaScript
>
> Call client functions directly wherever you need them. No provider required:
>
> ```typescript theme={"system"}
> import { getWalletAccounts } from "@dynamic-labs-sdk/client";
> import { dynamicClient } from "@/lib/dynamicClient";
>
> const user = dynamicClient.user;
> const walletAccounts = await getWalletAccounts();
> ```

> [tab] React
>
> Use hooks like `useUser`, `useGetWalletAccounts`, and `useInitStatus` from `@dynamic-labs-sdk/react-hooks` anywhere inside the providers (destructure values from `data`):
>
> ```tsx theme={"system"}
> import { useUser, useGetWalletAccounts, useInitStatus } from "@dynamic-labs-sdk/react-hooks";
>
> function Profile() {
>   const { data: initStatus } = useInitStatus();
>   const { data: user } = useUser();
>   const { data: walletAccounts = [] } = useGetWalletAccounts();
>
>   if (initStatus !== "finished") return <p>Loading…</p>;
>   if (!user) return <p>Not signed in</p>;
>
>   return <p>Wallet: {walletAccounts[0]?.address}</p>;
> }
> ```

You can customize the integration further by following the [JavaScript Quickstart](https://docs.dynamic.xyz/docs/javascript/reference/quickstart.md) or [React Quickstart](https://docs.dynamic.xyz/docs/javascript/reference/react-quickstart.md), or the generated project's README.

If you have any questions or need help with the integration, feel free to reach out to us in [Slack](https://dynamic.xyz/slack).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.