Skip to content

2. Installation & Setup

RAprogramm edited this page Nov 4, 2025 · 2 revisions

Chapter 2: Installation & Setup

This guide walks you through setting up your first Telegram Mini App with telegram-webapp-sdk.

Prerequisites

Before starting, ensure you have:

  1. Rust Toolchain (1.90 or later)

    # Check your version
    rustc --version
    
    # If you need to install/update
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  2. Telegram Bot

    • Create one via @BotFather
    • Send /newbot and follow instructions
    • Save your bot token (looks like 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw)
  3. Basic Rust Knowledge

    • Understanding of Cargo projects
    • Familiarity with either Yew or Leptos (recommended)

Quick Start

Step 1: Create New Project

# Create a new Rust project
cargo new my-telegram-app
cd my-telegram-app

Step 2: Add Dependencies

Edit Cargo.toml:

[package]
name = "my-telegram-app"
version = "0.1.0"
edition = "2021"

[dependencies]
# Core SDK with macros
telegram-webapp-sdk = { version = "0.3", features = ["yew", "macros"] }

# Yew framework
yew = { version = "0.21", features = ["csr"] }

For Leptos instead of Yew:

[dependencies]
telegram-webapp-sdk = { version = "0.3", features = ["leptos", "macros"] }
leptos = { version = "0.8", features = ["csr"] }

Step 3: Create index.html

Create index.html in your project root:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>My Telegram App</title>

    <!-- REQUIRED: Telegram WebApp script -->
    <script src="https://telegram.org/js/telegram-web-app.js"></script>
</head>
<body></body>
</html>

Important: The Telegram script must be loaded before your WASM bundle.

Step 4: Write Your App

Edit src/main.rs:

For Yew:

use telegram_webapp_sdk::{telegram_app, telegram_page, telegram_router, TelegramWebApp};
use yew::prelude::*;

#[telegram_page(path = "/")]
#[function_component(Home)]
fn home() -> Html {
    let webapp = TelegramWebApp::new();

    // Get user info from Telegram
    let user_name = webapp
        .init_data_unsafe()
        .user
        .as_ref()
        .map(|u| u.first_name.clone())
        .unwrap_or_else(|| "Guest".to_string());

    html! {
        <div>
            <h1>{ format!("Hello, {}!", user_name) }</h1>
            <p>{ "Welcome to your first Telegram WebApp!" }</p>
            <button onclick={Callback::from(move |_| {
                webapp.show_alert("Button clicked!");
            })}>
                { "Click Me" }
            </button>
        </div>
    }
}

#[telegram_app(auto_init)]
#[function_component(App)]
fn app() -> Html {
    telegram_router! {
        "/" => Home,
    }
}

fn main() {
    yew::Renderer::<App>::new().render();
}

For Leptos:

use telegram_webapp_sdk::{provide_telegram_context, TelegramWebApp};
use leptos::prelude::*;

#[component]
fn App() -> impl IntoView {
    // Provide Telegram context to child components
    provide_telegram_context();

    let webapp = TelegramWebApp::new();

    let user_name = move || {
        webapp
            .init_data_unsafe()
            .user
            .as_ref()
            .map(|u| u.first_name.clone())
            .unwrap_or_else(|| "Guest".to_string())
    };

    view! {
        <div>
            <h1>"Hello, " {user_name} "!"</h1>
            <p>"Welcome to your first Telegram WebApp!"</p>
            <button on:click=move |_| {
                webapp.show_alert("Button clicked!");
            }>
                "Click Me"
            </button>
        </div>
    }
}

fn main() {
    console_error_panic_hook::set_once();
    mount_to_body(|| view! { <App /> })
}

Step 5: Install Trunk

Trunk is the recommended build tool for Rust WASM apps:

cargo install trunk

Step 6: Build and Serve

# Development server (with hot reload)
trunk serve

# Production build
trunk build --release

Your app will be at http://localhost:8080 (development) or in dist/ folder (production).

Testing Locally

Option A: Mock Environment

For development without Telegram, enable the mock feature:

[dependencies]
telegram-webapp-sdk = { version = "0.3", features = ["yew", "macros", "mock"] }

Then initialize the mock:

#[cfg(feature = "mock")]
use telegram_webapp_sdk::mock::{init_mock, MockConfig, MockUser};

#[cfg(feature = "mock")]
fn setup_mock() {
    init_mock(MockConfig {
        user: Some(MockUser {
            id: 12345,
            first_name: "Test User".into(),
            username: Some("testuser".into()),
            ..Default::default()
        }),
        platform: "ios",
        version: "7.0",
        ..Default::default()
    });
}

Option B: HTTPS Tunnel

Telegram requires HTTPS. Use a tunnel to test with real Telegram:

cloudflared (Recommended)

# Install cloudflared
# https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/

# Terminal 1: Run your app
trunk serve

# Terminal 2: Create tunnel
cloudflared tunnel --url http://localhost:8080

You'll get a URL like https://random-name.trycloudflare.com.

ngrok

# Install ngrok
# https://ngrok.com/download

# Terminal 1: Run your app
trunk serve

# Terminal 2: Create tunnel
ngrok http 8080

You'll get a URL like https://abc123.ngrok.io.

Note: Tunnel URLs change on each restart. Update BotFather after restarting.

Configuring Your Bot

Step 1: Create WebApp in BotFather

  1. Open @BotFather
  2. Send /mybots
  3. Select your bot
  4. Choose "Bot Settings" → "Menu Button"
  5. Choose "Configure menu button"
  6. Send "Edit menu button URL"
  7. Enter your WebApp URL:
    • Development: https://your-tunnel-url.trycloudflare.com
    • Production: https://your-domain.com/index.html

Step 2: Test Your WebApp

  1. Open your bot in Telegram
  2. Click the menu button (bottom-left, next to message input)
  3. Your WebApp should open inside Telegram

Project Structure

After setup, your project should look like:

my-telegram-app/
├── Cargo.toml          # Dependencies
├── index.html          # HTML template with Telegram script
├── src/
│   └── main.rs         # Your app code
└── dist/               # Build output (after trunk build)
    ├── index.html
    ├── my-telegram-app-xxxxx.wasm
    └── my-telegram-app-xxxxx.js

Common Configuration

Adding More Features

Enable optional features in Cargo.toml:

[dependencies]
telegram-webapp-sdk = {
    version = "0.3",
    features = [
        "yew",        # Yew integration
        "leptos",     # Leptos integration (alternative to yew)
        "macros",     # Macros for routing and initialization
        "mock",       # Mock environment for testing
    ]
}

Feature descriptions:

  • yew - Yew framework integration (hooks, components)
  • leptos - Leptos framework integration (signals, components)
  • macros - Declarative macros (telegram_app!, telegram_page!, etc.)
  • mock - Mock Telegram environment for local testing

Optimizing Build Size

Create Trunk.toml in your project root:

[[hooks]]
stage = "build"
command = "sh"
command_arguments = ["-c", "wasm-opt -Oz -o dist/my-telegram-app_bg.wasm dist/my-telegram-app_bg.wasm"]

This requires wasm-opt to be installed:

# On macOS
brew install binaryen

# On Ubuntu/Debian
apt-get install binaryen

# On Windows (via scoop)
scoop install binaryen

Custom Public URL

For deployment to a subdirectory:

trunk build --release --public-url "https://your-domain.com/app/"

This ensures all assets load from the correct path.

Troubleshooting

"Telegram is not defined"

Symptom: Console error: Telegram is not defined

Solution: Ensure index.html loads the Telegram script:

<script src="https://telegram.org/js/telegram-web-app.js"></script>

This must be in <head> before your WASM bundle loads.

wasm-bindgen Version Mismatch

Symptom:

it looks like the Rust project used to create this Wasm file was linked against
version of wasm-bindgen that uses a different bindgen format than this binary:

  rust Wasm file schema version: 0.2.93
   this binary schema version: 0.2.92

Solution:

Option 1 - Install matching version:

cargo install wasm-bindgen-cli --version 0.2.93

Option 2 - Update dependencies:

cargo update
trunk build --release

WASM File Too Large

Symptom: WASM bundle is several MB

Solutions:

  1. Enable release mode:

    trunk build --release
  2. Optimize with wasm-opt (see "Optimizing Build Size" above)

  3. Add to Cargo.toml:

    [profile.release]
    opt-level = "z"     # Optimize for size
    lto = true          # Link-time optimization
    codegen-units = 1   # Better optimization

App Doesn't Load in Telegram

Checklist:

  • URL is HTTPS (not HTTP)
  • URL is publicly accessible (not localhost)
  • URL is configured in BotFather
  • Telegram script is loaded in index.html
  • No console errors in browser DevTools

Debug in Telegram Desktop:

  1. Open Telegram Desktop
  2. Enable Debug Menu: Settings → Advanced → Experimental → Enable WebView Inspecting
  3. Right-click WebApp → "Inspect"
  4. Check console for errors

Rust Version Too Old

Symptom: Compilation errors mentioning unstable features

Solution: Update Rust to 1.90+:

rustup update stable
rustc --version  # Should be 1.90 or later

Next Steps

Now that your project is set up, learn about the core concepts:

Chapter 3: Core Concepts

Additional Resources

Clone this wiki locally