Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
FREEDOM251

Freedom251 › Blog › E-commerce

How to Build a Vue Telegram Catalog with a Shared Pinia Cart

By Freedom251 Team · · 5 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Build the catalog and cart in Vue, use Pinia for cart state shared across screens, and let a trusted backend—not the Mini App—verify the user, recalculate prices, create the order, and confirm payment. Telegram provides the host interface and invoice-opening capability; it does not make browser-submitted cart data authoritative.

How the parts fit together

A sound implementation separates display, shared state, Telegram integration, and order authority:

As an Amazon Associate I earn from qualifying purchases.

  • Vue renders the catalog, cart, and checkout screens.
  • Pinia holds cart data and cart actions used by more than one component.
  • Telegram’s WebApp API supplies Mini App host information, interface features, and an invoice-opening interface.
  • Your backend validates Telegram launch data, loads current product records and prices, creates orders, and tracks payment and fulfillment.

The browser can show a provisional subtotal, but the server must determine the final amount. Treat submitted product IDs and quantities as a request, not proof of price, availability, identity, or payment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set up Vue and Pinia

Install Pinia and register a Pinia instance on the Vue application before mounting it. The official Pinia Getting Started guide shows the app setup and introduces stores as a place for shared state and business logic.

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')

Create a cart store with explicitly declared initial state, actions for mutations, and getters for values derived from that state. For example, store product identifiers and quantities in cart lines; derive the displayed item count from those lines. Pinia requires state properties to be declared in the state function; see its state documentation.

import { defineStore } from 'pinia'

export const useCartStore = defineStore('cart', {
  state: () => ({
    lines: []
  }),
  getters: {
    itemCount: (state) =>
      state.lines.reduce((total, line) => total + line.quantity, 0)
  },
  actions: {
    add(productId) {
      const line = this.lines.find(item => item.productId === productId)
      if (line) line.quantity += 1
      else this.lines.push({ productId, quantity: 1 })
    },
    setQuantity(productId, quantity) {
      const line = this.lines.find(item => item.productId === productId)
      if (!line) return
      if (quantity <= 0) this.remove(productId)
      else line.quantity = quantity
    },
    remove(productId) {
      this.lines = this.lines.filter(item => item.productId !== productId)
    }
  }
})

This example stores identifiers and quantities rather than treating browser-held product names or prices as authoritative. A UI may combine the cart lines with catalog data for display, but checkout should send only the requested items needed by the server to reconstruct the order.

Decide what belongs in Pinia

Use Pinia when the same cart must be read or changed by the catalog, cart, and checkout components. Keep one-off interface details—such as whether a particular menu is open—inside the component that owns that interface. This distinction avoids turning every temporary UI condition into global state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If you use server-side rendering, do not keep a mutable store singleton in module scope across server requests: it can lead to state being shared between users. Vue’s state management guide discusses this risk and recommends Pinia for new applications that need a store.

Connect to Telegram’s Mini App environment

Telegram’s Mini Apps documentation describes loading telegram-web-app.js and using window.Telegram.WebApp to interact with the host. Account for the possibility that the same app is opened in an ordinary browser preview, where the Telegram host object may be absent; guard calls that depend on it and provide a useful fallback rather than assuming every environment is Telegram.

Design for a mobile-first embedded view. Use Telegram’s live theme parameters instead of hard-coding a light or dark palette, respond to viewport changes, and respect safe-area insets so fixed cart or checkout controls do not collide with host UI. Keep controls usable on small screens, and provide labels for inputs and meaningful text alternatives for images, as Telegram’s design guidance recommends.

Validate launch data before identifying the user

Do not use initDataUnsafe as proof of identity. Telegram explicitly warns that it should not be trusted. Send the raw initData string to your backend and validate it there using Telegram’s documented procedure before relying on the identity or other fields it contains. Apply an appropriate freshness check as part of that validation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A user ID copied from frontend state is not authentication. The backend should associate an order with a Telegram user only after validating the launch data; see Telegram’s current Mini Apps documentation for the validation requirements.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Build checkout around a server-authoritative order

A practical flow keeps order decisions on the server while letting Vue handle the interaction:

  1. Review: Show the cart lines and a clearly provisional subtotal in the Mini App.
  2. Submit: Send product identifiers and quantities to the backend along with the raw Telegram initData.
  3. Validate and price: The backend validates the launch data, reloads current product records, checks availability, and calculates the amount from authoritative prices.
  4. Create the order and invoice: The backend creates an order and obtains the applicable Telegram invoice or payment flow for the product and selected provider.
  5. Open the invoice: The Mini App invokes the documented invoice-opening interface.
  6. Reconcile: Record payment and fulfillment state using the backend’s order/payment record before displaying a confirmed order or fulfilling it.

Telegram documents payment support through third-party providers and the Mini App openInvoice interface. Requirements depend on what is being sold and the selected provider, so check the current Telegram documentation and provider terms rather than assuming one universal payment route, fee, or regional availability.

Handle invoice outcomes without guessing

Keep pending, successful, and cancelled outcomes distinct in the interface. Telegram documents invoice status reporting through the corresponding close event, but closing the invoice UI alone is not proof that an order was paid. Reconcile the reported outcome with the backend order/payment record before presenting success or starting fulfillment. If the record is still pending, show that state and let the backend’s payment handling determine the next step.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose the right implementation boundaries

Decision Use this approach Reason
Cart state Pinia for cart contents shared across screens; component-local state for isolated UI details. Shared cart operations belong in shared application state; transient controls need not be global.
Prices and order validity Backend recalculation and validation; browser totals are display-only. Client state can be changed and is not proof of a valid price or order.
Rendering mode Client rendering is straightforward; if using SSR, avoid a mutable cross-request store singleton. Server requests must not share user-specific mutable state.
Host integration Use Telegram’s host API in the Mini App and guard for its absence in browser previews. The host object is not available in every environment where the web app may be opened.
Payment route Choose the supported invoice/payment route and provider based on the product, geography, and current requirements. Platform and provider rules are not universal across products or regions.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

E-commercePiniaTelegram Mini AppsVueWeb development

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.