DEV Community

Cover image for Telegram Web App with React and Next.js
Alexey Nikolaev
Alexey Nikolaev

Posted on

168

Telegram Web App with React and Next.js

One of the recent Telegram updates finally brought full power of web apps right into Telegram messenger. It means that from now on any dev can embed an MMO game, a ticket store or any other app inside built-it Telegram browser and make it available for 700 millions of users. There is no limits, it's fully functional browser inside messenger.

Telegram Web App API provides user information, theme scheme, haptic feedback (only on mobile/laptop devices), access to video and audio streams. You can check this bot test all possibilities and see what information is provided to web app -- https://t.me/asmico_attach_bot


In order to build you own web app for Telegram with React and Next.js you'll need to get information from the app. I'd like to share some code snippets and tips that you can copy-paste and use for a quicker start.

As a first step let's add types to know what data is available for you:

// types.ts
export interface ITelegramUser {
  id: number;
  first_name: string;
  last_name: string;
  username: string;
  language_code: string;
}

export interface IWebApp {
  initData: string;
  initDataUnsafe: {
    query_id: string;
    user: ITelegramUser;
    auth_date: string;
    hash: string;
  };
  version: string;
  platform: string;
  colorScheme: string;
  themeParams: {
    link_color: string;
    button_color: string;
    button_text_color: string;
    secondary_bg_color: string;
    hint_color: string;
    bg_color: string;
    text_color: string;
  };
  isExpanded: boolean;
  viewportHeight: number;
  viewportStableHeight: number;
  isClosingConfirmationEnabled: boolean;
  headerColor: string;
  backgroundColor: string;
  BackButton: {
    isVisible: boolean;
  };
  MainButton: {
    text: string;
    color: string;
    textColor: string;
    isVisible: boolean;
    isProgressVisible: boolean;
    isActive: boolean;
  };
  HapticFeedback: any;
}

Enter fullscreen mode Exit fullscreen mode

As a next step, let's create a context provider and custom hook for Telegram Web App data:

// TelegramProvider
import Script from "next/script";
import { createContext, useContext, useEffect, useMemo, useState } from "react";
import type { ITelegramUser, IWebApp } from "types";

export interface ITelegramContext {
  webApp?: IWebApp;
  user?: ITelegramUser;
}

export const TelegramContext = createContext<ITelegramContext>({});

export const TelegramProvider = ({
  children,
}: {
  children: React.ReactNode;
}) => {
  const [webApp, setWebApp] = useState<IWebApp | null>(null);

  useEffect(() => {
    const app = (window as any).Telegram?.WebApp;
    if (app) {
      app.ready();
      setWebApp(app);
    }
  }, []);

  const value = useMemo(() => {
    return webApp
      ? {
          webApp,
          unsafeData: webApp.initDataUnsafe,
          user: webApp.initDataUnsafe.user,
        }
      : {};
  }, [webApp]);

  return (
    <TelegramContext.Provider value={value}>
      {/* Make sure to include script tag with "beforeInteractive" strategy to pre-load web-app script */}
      <Script
        src="https://telegram.org/js/telegram-web-app.js"
        strategy="beforeInteractive"
      />      {children}
    </TelegramContext.Provider>
  );
};

export const useTelegram = () => useContext(TelegramContext);
Enter fullscreen mode Exit fullscreen mode

As a final step let's use it for our test WebApp page:

// pages/webapp.tsx
import { TelegramProvider, useTelegram } from "lib/TelegramProvider";

const WebApp = () => {
  const { user, webApp } = useTelegram();
  console.log(user);

  return (
    <div>
      {user ? (
        <div>
          <h1>Welcome {user?.username}</h1>
          User data:
          <pre>{JSON.stringify(user, null, 2)}</pre>
          Eniter Web App data:
          <pre>{JSON.stringify(webApp, null, 2)}</pre>
        </div>
      ) : (
        <div>Make sure web app is opened from telegram client</div>
      )}
    </div>
  );
};

const WithTelegramProvider = () => {
  return (
    <TelegramProvider>
      <WebApp />
    </TelegramProvider>
  );
};
Enter fullscreen mode Exit fullscreen mode

or make it available globally by providing Telegram context on the top level at _app.tsx

// _app.tsx
import { TelegramProvider } from "lib/TelegramProvider";
import type { AppProps } from "next/app";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <TelegramProvider>
      <Component {...pageProps} />
    </TelegramProvider>
  );
}

export default MyApp;
Enter fullscreen mode Exit fullscreen mode

That's it! Happy hacking 🔥
Learn more about Telegram Web Apps on their website: https://core.telegram.org/bots/webapps

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (4)

Collapse
 
t00kind profile image
Ildar •

I use this templete but got f***king undefined object, not Telegram web app. I'm sure that I test it in Telegram client -desktop & mobile. To debug it I used vscode ports

my code: github.com/t00kind/tracker

Collapse
 
olabima_ profile image
Bima •
<Head>
        <script src="https://telegram.org/js/telegram-web-app.js"></script>
  </Head>
Enter fullscreen mode Exit fullscreen mode

Add this to your entry file i.e. layout or index or _app or whatever and you will not get a f**king undefined object anymore. And Alexey thanks for this

Collapse
 
dannylin108 profile image
Danny Lin •

Is there a repo with asmico_attach_bot code? Would be very helpful!
Thanks a lot!

Collapse
 
jefferson_liew_99c09ed85d profile image
Jefferson Liew •

How can I make it available globally if I'm using React only and not Next

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

đź‘‹ Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay