Skip to content

System context

A newcomer who needs the big picture before any detail: who touches the system, what it talks to, and where its responsibility ends.

  • Five kinds of people use the system: the guest, the event operator, the lead admin in a Telegram group, the site visitor (an event organiser) and the developer/owner.
  • The system depends on Telegram (Bot API and public t.me pages), two AI providers (Gemini primary, OpenAI fallback), Vercel (landing hosting) and one DigitalOcean droplet (API, bot, database, files).
  • The guest never installs anything and never creates an account: a QR code and their own Telegram are enough.
  • The result is a real Telegram sticker set owned by the guest’s Telegram account, delivered as a link in the bot.
  • The system does not take payments, does not keep photos (files are deleted within PHOTO_TTL_HOURS, at most 72 hours) and does not expose any webhook to Telegram.
flowchart TB
    guest["Guest at an event"]
    operator["Event operator or staff"]
    leadadmin["Lead admin in the Telegram group"]
    visitor["Site visitor - event organiser"]
    dev["Developer and owner"]

    system["AI Sticker Pack - kiosk page, API, bot with worker, landing page"]

    telegram["Telegram - Bot API, t.me pages, client apps"]
    ai["AI providers - Gemini primary, OpenAI fallback"]
    vercel["Vercel - hosts the landing page"]
    droplet["DigitalOcean droplet - hosts API, bot, database, files"]
    tls["DNS and Let's Encrypt certificates via Caddy"]

    guest -- "taps Start, picks an outfit, is photographed" --> system
    guest -- "scans QR, gives consent, receives the pack link" --> telegram
    operator -- "sets up the tablet, watches the admin panel and alerts" --> system
    leadadmin -- "presses status buttons, runs group commands" --> telegram
    visitor -- "reads the landing, submits a request" --> system
    dev -- "deploys over SSH, edits configuration" --> system

    system -- "long polling, messages, sticker set creation" --> telegram
    system -- "selfie and prompt in, sticker sheets and JSON out" --> ai
    system -. "landing runs on" .-> vercel
    system -. "server parts run on" .-> droplet
    system -. "HTTPS certificates" .-> tls

Solid arrows are interactions. Dotted arrows mean “is hosted on” or “depends on for infrastructure”.

Person What they do How they reach the system
Guest Taps Start on the tablet, scans the QR code with their phone, presses the consent button in the bot, picks an outfit on the tablet, looks at the camera, later opens the sticker set link The kiosk page on the tablet, and a private chat with the Telegram bot on their own phone
Event operator / staff Opens the kiosk page on the tablet, grants camera permission once, resets a stuck station (long press on a hidden zone), watches the admin panel, reacts to alerts, grants an extra pack or retries a failed job The kiosk page; the web admin panel at https://stickers.eventtalks.uz/admin (HTTP Basic); bot commands /stats, /admin_stats, /pause, /resume for the Telegram users listed in ADMIN_USER_IDS; alert messages in the chat set by ADMIN_CHAT_ID
Lead admin Works with requests from organisers: presses a status button on a request card, lists open requests, exports CSV, erases a person’s data on request The Telegram group set by LEADS_CHAT_ID. Only the Telegram users listed in LEADS_ADMIN_IDS may press buttons or run /stickers_* commands
Site visitor / organiser Reads the landing page in Russian, Uzbek or English and submits the request form https://pack.eventtalks.uz in a browser
Developer / owner Changes code, deploys, edits bot/.env, tops up the AI provider balance SSH to the droplet (deploy scripts in deploy/), the Vercel project, the AI provider consoles

One person may hold several roles. The roles are separated by configuration, not by accounts in the system: ADMIN_USER_IDS, LEADS_ADMIN_IDS, the admin panel login and SSH access are four independent lists.

System What it is used for Direction
Telegram Bot API Receiving updates by long polling (getUpdates), sending messages, createNewStickerSet, getStickerSet, getChat, getChatMember, setMyCommands The server always opens the connection. There is no webhook, so Telegram never connects to the server
t.me public pages The deep link in the QR code (https://t.me/<bot_username>?start=<session_token>), the pack link (https://t.me/addstickers/<pack_name>) and the readiness check: the bot fetches the pack page and reads its og:title Guest’s phone opens the links; the bot fetches the pack page over HTTPS
Gemini (Google) — primary AI provider Image generation (sticker sheets, anchor portrait, single-figure regeneration) and cheap vision calls that return JSON (appearance description, quality checks) The bot process calls the provider SDK over HTTPS
OpenAI — fallback AI provider The same two roles when the primary provider fails for a call. Which provider is primary is configuration (PRIMARY_AI_PROVIDER, FALLBACK_AI_PROVIDER), not code The bot process calls the provider SDK over HTTPS
Vercel Hosts the Next.js landing page and runs its server action. The landing domain is set there through NEXT_PUBLIC_SITE_URL; it is not stored in the repository The server action calls the leads endpoint, and Telegram directly as a fallback
DigitalOcean One droplet runs Caddy, sticker-api, sticker-bot, the SQLite file and the photo files. The droplet is shared with a second, unrelated project —
DNS and Let’s Encrypt Caddy obtains and renews the certificate for stickers.eventtalks.uz automatically. HTTPS is mandatory: the browser camera API (getUserMedia) works only on HTTPS or localhost. Where the DNS zone is hosted is not recorded in either repository Caddy contacts Let’s Encrypt
  • Links a tablet session to a Telegram user through a one-time QR token.
  • Records explicit consent before anything else happens; without it the outfit screen never opens.
  • Accepts one photo per session, strips EXIF by re-encoding, and queues a generation job.
  • Generates 12 stickers of the guest with an image model, checks them, and repairs single stickers when a check fails.
  • Creates a Telegram sticker set in the guest’s name and sends the link only after the set is confirmed to open.
  • Enforces a pack limit per Telegram account: one pack, plus extra packs granted by an operator.
  • Records every AI call with an estimated cost, stops a job that exceeds JOB_MAX_COST_USD, and pauses new jobs when the provider reports that the balance is exhausted.
  • Deletes photos and derived images by TTL and clears the textual appearance description when a job ends.
  • Accepts organiser requests from the landing page, stores them, posts them to a Telegram group, reminds about unhandled ones, sends a daily digest and anonymises old ones.
Not done What happens instead / why it matters
No payments, invoices or pricing logic Sales happen outside the system; the landing form only collects a request
No guest accounts, passwords or e-mail Identity is the guest’s Telegram user id
No Telegram webhook The bot long-polls. The only inbound HTTP on the server is the kiosk, the admin panel and POST /leads
No photo in the database The database stores a file path only; the file lives on disk until the pack is created or the TTL passes
No result on the tablet The kiosk never waits for generation. The pack arrives in Telegram
No outfit choice in the bot Outfits are chosen on the tablet, after consent
No deletion or re-creation of a sticker set on Telegram A created set is never deleted or recreated under the same name, because Telegram clients cache the state of a name. Resetting a guest in the admin panel removes database rows, not the set
No multi-tenancy One bot token, one database, one kiosk domain. See Multi-tenant
No CRM, mailing or lead scoring A lead has six statuses and a history of who changed them; everything else is manual
No Docker Processes run directly under systemd from a Python virtual environment

Last verified: 2026-11-13 against ai-sticker-pack@b715418 and ai-stickers-landing@e350ff5.