Telegram Mini Apps React Template

repository·master·Indexed 19 days ago

https://github.com/telegram-mini-apps/reactjs-template

A React-based template for building Telegram Mini Apps using TypeScript and Vite. It features pre-integrated support for the @tma.js SDK and TON Connect, and includes utility components for theme management, platform detection, and Telegram-specific UI elements like the back button and internal/external link handling.

Tokens
5.5K
Snippets
20
Records
23
Agent score
64%

What's inside reactjs-template

  1. Run the application in development mode

    master

    To develop and test the Mini App outside of Telegram, use the dev:https script. This uses vite-plugin-mkcert to provide valid SSL certificates, which is necessary for certain features.

    Note on SSL: When running dev:https for the first time, you may be prompted for your sudo password to configure the certificates. If you wish to avoid this, use npm run dev instead, but be aware that SSL is not configured.

    Warning for Mobile Testing: Because the template uses self-signed SSL certificates in development, the Android and iOS Telegram applications will not be able to load the app due to strict security measures. For remote testing on mobile, refer to the Telegram platform guide.

    Mocking the Telegram Environment: The template uses src/mockEnv.ts (imported in src/index.ts) which employs the mockTelegramEnv function. This simulates the Telegram environment so that libraries like @tma.js/sdk function correctly in a standard browser. Do not use this mock function in production.

    npm run dev:https
  2. Configure and deploy to GitHub Pages manually

    master

    The template uses the gh-pages tool for manual deployment. Follow these steps to ensure correct asset paths and routing:

    1. Update package.json: Set the homepage field to your GitHub Pages URL. Example: "homepage": "https://username.github.io/repo-name"

    2. Update vite.config.ts: Set the base value to your repository name. Example: base: '/repo-name/'

    3. Build the project:

      npm run build
    4. Deploy:

      npm run deploy
    {
      "homepage": "https://telegram-mini-apps.github.io/is-awesome"
    }
    export default defineConfig({
      base: '/is-awesome/',
      // ...
    });
  3. Configure automatic deployment via GitHub Workflow

    master

    The template includes a pre-configured GitHub workflow located at .github/workflows/github-pages-deploy.yml that automatically deploys to GitHub Pages when changes are pushed to the master branch.

    To enable this:

    1. Go to your GitHub repository settings.
    2. Create or edit an environment named github-pages.
    3. Add the master branch to the list of deployment branches.

    If you prefer manual deployment or do not use GitHub, you can remove the .github directory.

  4. Mock the Telegram environment for macOS compatibility

    master

    When mockForMacOS is enabled in the init function, the application uses mockTelegramEnv to intercept and fix specific Telegram client events that are known to be buggy on macOS.

    Specifically, it handles:

    1. web_app_request_theme: Ensures theme parameters are correctly retrieved from retrieveLaunchParams().tgWebAppThemeParams on the first request, or from the current themeParams.state() on subsequent requests, and emits a theme_changed event.
    2. web_app_request_safe_area: Intercepts the request and emits a safe_area_changed event with zeroed-out margins (left: 0, top: 0, right: 0, bottom: 0) to prevent incorrect safe area calculations.
  5. Available npm scripts

    master

    Use npm run {script} to execute the following commands:

    • dev: Runs the application in development mode.
    • dev:https: Runs the application in development mode using locally created valid SSL-certificates (recommended for testing).
    • build: Builds the application for production.
    • lint: Runs eslint to ensure code quality.
    • deploy: Deploys the application to GitHub Pages.
    npm run build
  6. Use the ErrorBoundary component to catch component errors

    master

    The ErrorBoundary component is a React class component used to catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed.

    It supports two types of fallback mechanisms via the fallback prop:

    1. A React Node: A static piece of UI (like a <div> or a custom component) that is rendered when an error occurs.
    2. A Component Type: A functional component that receives the error as a prop: <Fallback error={error} />. This allows you to build dynamic error displays that react to the specific error caught.
    import { ErrorBoundary } from './components/ErrorBoundary';
    
    // Option 1: Using a static React Node as fallback
    <ErrorBoundary fallback={<div>Something went wrong.</div>}>
      <MyComponent />
    </ErrorBoundary>
    
    // Option 2: Using a custom component that receives the error
    const MyErrorDisplay = ({ error }: { error: unknown }) => (
      <div>
        <h2>An error occurred:</h2>
        <pre>{String(error)}</pre>
      </div>
    );
    
    <ErrorBoundary fallback={MyErrorDisplay}>
      <MyComponent />
    </ErrorBoundary>
  7. Resolve public URLs with publicUrl()

    master

    Use the publicUrl helper to generate absolute URLs for static assets by prepending the application's base URL. This ensures that assets like tonconnect-manifest.json are correctly resolved regardless of whether the app is hosted at the domain root or a subpath.

    Important usage rules:

    • Do not include a leading slash in the path argument. The function internally handles path joining, and providing a leading slash (e.g., /manifest.json) may cause the URL constructor to ignore the base path.
    • The function automatically uses import.meta.env.BASE_URL as the prefix.
    • If the base URL is relative, it automatically resolves against window.location.origin.
    import { publicUrl } from './helpers/publicUrl';
    
    // Correct usage: no leading slash
    const manifestUrl = publicUrl('tonconnect-manifest.json');
    
    // Incorrect usage: leading slash might break base URL resolution
    const badUrl = publicUrl('/tonconnect-manifest.json');
  8. Join CSS class names with classNames()

    master

    The classNames function joins multiple values into a single space-separated string of CSS classes. It follows these rules:

    1. Strings: Non-empty strings are added directly to the output.
    2. Objects: Only keys with truthy values are added to the output.
    3. Arrays: Arrays are spread and processed recursively.
    4. Other values: All other types (numbers, booleans, null, undefined) are ignored.

    This function behaves similarly to the popular classnames npm package.

    import { classNames } from './src/css/classnames';
    
    // Basic usage
    classNames('btn', 'btn-primary'); // 'btn btn-primary'
    
    // Using objects for conditional classes
    classNames('btn', { 'btn-active': true, 'btn-disabled': false }); // 'btn btn-active'
    
    // Using arrays
    classNames(['btn', 'btn-large'], 'btn-red'); // 'btn btn-large btn-red'
    
    // Nested structures
    classNames('base', ['nested', { active: true }]); // 'base nested active'
  9. Use the bem utility to generate BEM class names

    master

    The bem utility provides a way to generate CSS class names following the Block Element Modifier (BEM) methodology. It returns a tuple containing two functions: a BlockFn for the main block and an ElemFn for elements within that block. Both functions support modifiers passed as strings, arrays of strings, or objects where the key is the modifier name and the value is a boolean determining if it should be applied.

    import { bem } from '@/css/bem.js';
    
    const [classBlock, classElem] = bem('button');
    
    // Block with modifiers
    // Result: "button button--large button--primary"
    const blockClass = classBlock('large', 'primary');
    
    // Block with object-based modifiers
    // Result: "button button--active"
    const blockClassObj = classBlock({ active: true, disabled: false });
    
    // Element with modifiers
    // Result: "button__icon button__icon--small"
    const elemClass = classElem('icon', 'small');
    
    // Element with object-based modifiers
    // Result: "button__text button__text--bold"
    const elemClassObj = classElem('text', { bold: true });
  10. Configure back button visibility in the Page component

    master

    The Page component accepts a back prop to control the Telegram back button:

    • back={true} (default): Shows the Telegram back button and configures it to navigate to the previous page in the history stack.
    • back={false}: Hides the Telegram back button.
    // Shows back button and enables navigation
    <Page back={true}>...</Page>
    
    // Hides the back button
    <Page back={false}>...</Page>