This is a template for quickly create Telegram Web Apps using Next.js and Tailwind CSS.
Next.js is easy and powerful, it also allows creating API routes without the need of another server and any troubles, example, it's ideal for validating the incoming web app's request hash.
Execute create-next-app
with pnpm to create a new project:
pnpm create next-app --example https://github.com/mauriciobraz/next.js-telegram-webapp your-app-name
Now, clone the .env.example
file and rename it to .env.local
and fill the variables with your own data.
BOT_TOKEN
: Your Telegram Bot Token (used for validating the incoming requests, see Request Validation for more info)
pnpm dev
Testing locally w/ ngrok
Since Telegram only accepts HTTPS links, you'll need to use a tunneling service like ngrok to test your bot locally.
# Copy the HTTPS URL given by ngrok and use it as main URL for your bot.
# If the port differs from 3000, change it accordingly.
ngrok http 3000
This template is already configured to use @next/bundle-analyzer, that is a plugin for Next.js that analyzes the bundle size of your application (useful when you want to replace a library with another one that is smaller). The following command will generate a report in the .next/analyze
folder and open it in your browser.
pnpm analyze
All the requests are validated using an API route that checks if the request is coming from Telegram. Telegram's documentation explains how it works.
To disable this feature, delete the pages/api/validate-hash.ts
file and remove the useEffect
hook from pages/_app.tsx
and it's dependencies.
# src/pages/_app.tsx
import type { AppProps } from 'next/app';
- import { useEffect, useState } from 'react';
- import axios from 'axios';
function MyApp({ Component, pageProps }: AppProps) {
- const [isHashValid, setIsHashValid] = useState(false);
- // Wait for validation to complete before rendering the page and stop the
- // rendering if the hash is invalid. Comment out the following useEffect
- // hook to see the page render without the hash validation.
- useEffect(() => {
- axios
- .post('/api/validate-hash', { hash: window.Telegram.WebApp.initData })
- .then(response => setIsHashValid(response.status === 200));
- }, []);
- if (!isHashValid) {
- return null;
- }
return <Component {...pageProps} />;
}
Using initData
You can use in the window.Telegram.WebApp.initDataUnsafe
but it's not recommended by Telegram. There's the hook useTelegramInitData
that parses the data and returns an object.
// src/pages/init-data.tsx
import { useTelegramInitData } from '../hooks/useTelegramInitData';
export default function InitData() {
const initData = useTelegramInitData();
return (
<div>
<h1>initData</h1>
<pre>{JSON.stringify(initData, null, 2)}</pre>
</div>
);
}
Telegram's colors are already defined in the tailwind.config.js
file. You can use them in your components with the following directives (see Tailwind's documentation for more info):
Tailwind Directive's Name | Telegram's Color Variable | Fallback Color |
---|---|---|
telegram-white |
var(--tg-theme-bg-color) |
#ffffff |
telegram-black |
var(--tg-theme-text-color) |
#000000 |
telegram-hint |
var(--tg-theme-hint-color) |
#707579 |
telegram-link |
var(--tg-theme-link-color) |
#3390ec |
telegram-primary |
var(--tg-theme-button-color) |
#3390ec |
telegram-primary-text |
var(--tg-theme-button-text-color) |
#ffffff |
telegram-secondary-white |
var(--tg-theme-secondary-bg-color) |
#f4f4f5 |
// src/components/Example.tsx
import type { FC } from 'react';
const Example: FC = () => {
return (
<div className="bg-telegram-white text-telegram-black flex w-full flex-1 flex-col items-center justify-center px-4 text-center">
<h1 className="text-2xl">Example</h1>
<p className="text-sm">This is an example component.</p>
</div>
);
};
export default Example;