DEV Community

Serhii
Serhii

Posted on Originally published at botservice.biz

Integrate Telegram WebApp in Vue 3: Theme, ViewportStable, and Secure Data Transfer

Introduction

We will build a Vue 3 single‑file component that loads the Telegram WebApp library, reads the initData passed in the URL, applies the current theme, locks the viewport, and sends a custom payload to the bot using window.Telegram.WebApp.sendData. The bot receives the data via a regular webhook and validates the initData string to ensure it originates from Telegram. We do not cover payment handling, inline keyboards, or long‑polling; the focus is strictly on the Mini App integration flow.

Main path

1. Vue component

<template>
  <div id="app">
    <h1>Telegram Mini App</h1>
    <button @click="sendPayload">Send data</button>
    <pre>{{ response }}</pre>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';

const response = ref('');

function initWebApp() {
  if (!window.Telegram?.WebApp) {
    console.warn('Telegram WebAPI not available');
    return;
  }
  const tg = window.Telegram.WebApp;

  // Expand to full height
  tg.expand();

  // Apply the current theme (optional but recommended)
  tg.ready();
  tg.themeChanged(); // triggers if theme already set

  // Lock viewport to prevent scaling on iOS/Android
  if (tg.viewportStable) {
    tg.viewportStable();
  }

  // Expose initData for later use
  tg.initDataUnsafe && console.log('initDataUnsafe', tg.initDataUnsafe);
}

function sendPayload() {
  if (!window.Telegram?.WebApp) {
    alert('WebApp not ready');
    return;
  }
  const payload = { action: 'demo', ts: Date.now() };
  window.Telegram.WebApp.sendData(JSON.stringify(payload));
}

// Listen for data sent from the WebApp (when the bot replies via web_app_data)
function listenForBotData() {
  if (!window.Telegram?.WebApp) return;
  window.Telegram.WebApp.onEvent('web_app_data', (event) => {
    response.value = event.data;
  });
}

onMounted(() => {
  initWebApp();
  listenForBotData();
});
</script>

<style scoped>
#app { font-family: sans-serif; margin: 2rem; }
button { padding: 0.5rem 1rem; font-size: 1rem; }
pre { background: #f4f4f4; padding: 1rem; }
</style>
Enter fullscreen mode Exit fullscreen mode

2. HTML entry point

Create public/index.html (or adjust your build) and add the Telegram script before the Vue app mounts:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Telegram Mini App Vue</title>
  <!-- Telegram WebApp SDK -->
  <script src="https://telegram.org/js/telegram-web-app.js"></script>
</head>
<body>
  <div id="app"></div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

The script makes window.Telegram.WebApp available as soon as the page loads inside the Telegram client.

3. PHP backend – validate initData and handle web_app_data

When the Mini App calls sendData, the bot receives an update of type web_app_data. The payload is in update.web_app_data.data. Before trusting it, verify the accompanying initData (available as update.web_app_data.init_data or passed separately) using the bot token.

<?php
// validate_initdata.php
$initData = $_POST['initData'] ?? $_GET['initData'] ?? '';
$data     = $_POST['data'] ?? '';

if (!$initData || !$data) {
    http_response_code(400);
    exit('Missing parameters');
}

$botToken = getenv('TELEGRAM_BOT_TOKEN');
if (!$botToken) {
    http_response_code(500);
    exit('Bot token not configured');
}

/**
 * Compute the SHA256 HMAC of the data check string.
 * See https://core.telegram.org/bots/webapps#validating-data-received-via-the-mini-app
 */
function checkInitData(string $token, string $initData): bool {
    // Parse key=value pairs
    parse_str($initData, $params);
    $hash = $params['hash'] ?? '';
    unset($params['hash']);

    // Build data check string sorted alphabetically
    ksort($params);
    $lines = [];
    foreach ($params as $key => $value) {
        $lines[] = "$key=$value";
    }
    $dataCheckString = implode("\n", $lines);

    $secretKey = hash('sha256', $token, true);
    $calculatedHash = hash_hmac('sha256', $dataCheckString, $secretKey);

    return hash_equals($hash, $calculatedHash);
}

if (!checkInitData($botToken, $initData)) {
    http_response_code(403);
    exit('Invalid initData');
}

// At this point $data is safe to use
error_log("Received valid data: $data");
// Process $data as needed (e.g., store, forward, reply)
echo json_encode(['status' => 'ok']);
Enter fullscreen mode Exit fullscreen mode

4. Wiring the Vue component to the backend

Replace the sendPayload function with an AJAX call that forwards the payload together with the initData:

async function sendPayload() {
  if (!window.Telegram?.WebApp) {
    alert('WebApp not ready');
    return;
  }
  const payload = { action: 'demo', ts: Date.now() };
  try {
    const resp = await axios.post('https://your-domain.com/validate_initdata.php', {
      initData: window.Telegram.WebApp.initDataUnsafe,
      data: JSON.stringify(payload)
    });
    response.value = JSON.stringify(resp.data);
  } catch (e) {
    response.value = 'Error: ' + e.message;
  }
}
Enter fullscreen mode Exit fullscreen mode

Production notes

  • HTTPS: The Mini App must be served over a valid TLS certificate; otherwise Telegram blocks the WebApp SDK.
  • CSP: If you use a Content‑Security‑Policy, allow script src="https://telegram.org" and connect-src to your backend.
  • Idempotency: Store a hash of received initData (or the update_id from the webhook) in Redis or a DB to prevent processing the same update twice.
  • Error handling: Always check the HTTP status of requests to Telegram and log ok:false responses from getMe or sendMessage when you later reply to the user.
  • Viewport: Calling viewportStable() after expand() prevents layout jumps on devices with unsafe‑area insets.
  • Theme updates: Re‑call themeChanged() whenever you receive a theme_changed event if you need to adapt colors dynamically.

This completes a minimal but functional Vue 3 Telegram Mini App that safely exchanges data with a bot. For further reading on the Bot API, see https://botservice.biz/telegram-bot-api.

BotCreator — studio that ships Telegram bots / Mini Apps.

Top comments (0)