Skip to main content

Dieta e Treino: Telegram bot & web dashboard

Full-stack engineer · 2026 · Shipped 2026 · 4 min read

Telegram-first food and training log, on-demand dashboard, opt-in Groups, and a Stripe trial.

Dieta e Treino: Telegram bot & web dashboard product interface
Rejected path: Build on WhatsApp Business API / Cloud API instead (higher ops overhead for this scale and use case)

Overview

Dieta e Treino started from a simple idea: keep food and training in the chat people already use, then open a panel only when they want the bigger picture. The same bot works in private chat or inside Telegram groups. Meals go through Ana (text, photo, or voice); workouts through Renan. When someone wants day totals, ~70-day consistency, or a light comparison with peers, they ask for the panel and open the link. Day-to-day logging stays in chat; the web app covers aggregated views, marketing, and billing.

Problem

Memory skews toward extremes. Without a steady record it is hard to see what you actually eat across days, or how training volume and frequency move over time. Consumer diet apps add installs and logins that break the habit before it starts.

Constraints

  • Self-hosted workflow runner for the bot (no managed cloud bill). Production ships as one bundled worker while the repo stays modular.
  • Telegram webhook delivery is time-bounded; the handler must finish in time and stay idempotent so retries do not double-write. Shared groups add noise, so heuristics catch food and workouts without requiring a slash command on every line.
  • Dashboard access is a short-lived link from the bot. Privileged database access stays server-side. Group ranking is opt-in in the bot, never automatic; peers see aggregates, not meal text.
  • Bot and dashboard must agree on each user’s local calendar day. Clock-sensitive UI renders on the client to avoid SSR/hydration mismatch.
  • Commercial path mirrors StackBrief (Checkout / Portal / webhooks, 14-day trial without card, soft-block of bot writes after trial) while keeping one Telegram identity = one subscription and privacy rules intact.

Architecture

Telegram triggers a self-hosted Windmill webhook; a bundled Bun job runs the bot. Gemini parses and transcribes; Postgres (Supabase) holds state. The webhook path finishes with a safe response after persist so retries stay clean. The dashboard is Next.js on Vercel with a Portuguese marketing landing (Ana/Renan, pricing, FAQ) and a token-gated panel: macros, heatmaps, training volume, Groups, and subscription. Structured events feed a scheduled quality digest; optional Sentry covers production errors. Lightweight ops alerts stay out of the user path.

Key Decisions

Telegram instead of WhatsApp as the chat surface

Reasoning

People already live in messaging apps; the goal was no new install. Telegram’s Bot API fits a small, iterative product: straightforward webhooks, bots in private chats and groups, and room to change how the bot behaves without a business-console workflow. WhatsApp’s path for comparable automation is heavier (Business API, stricter messaging rules, and cost signals that did not match this product).

Alternatives considered
  • Build on WhatsApp Business API / Cloud API instead (higher ops overhead for this scale and use case)
  • A standalone mobile app (rejected: extra install and separate login)

Self-hosted Windmill instead of cloud or a custom Node service

Reasoning

Workflows, retries, and schedules in one place; cost is the box I already have. Tradeoff is ops on that host.

Alternatives considered
  • Windmill Cloud or Railway/Fly with hand-rolled workers (extra cost or glue for the same outcome)

Named agents (Ana / Renan) instead of a single generic bot voice

Reasoning

Food and training are different intents in chat. Named agents make that split obvious in the bot and on the landing page.

Alternatives considered
  • One unnamed assistant for everything (cheaper copy, weaker mental model)

Gemini for text, image, and voice; heuristics for group noise

Reasoning

One API key and quota. Keywords and patterns filter the group so we do not call a model on every irrelevant line.

Alternatives considered
  • Slash-only commands or a classifier on every message (friction or cost)

Productize with Stripe trial + Telegram subscribe path

Reasoning

Early users proved the loop; a public site and paid tier need the same access rules as StackBrief without breaking the bot-first habit. Trial starts on authorize; after trial, soft-block writes while the panel still offers the subscription screen.

Alternatives considered
  • Keep the product invite-only with no billing
  • Force web signup before any Telegram use (rejected: breaks the core promise)

Tech stack

  • TypeScript (Bun on Windmill)
  • Windmill (self-hosted)
  • Supabase (PostgreSQL, RLS)
  • Google Gemini
  • Telegram Bot API
  • Next.js (App Router, Server Components)
  • React, Tailwind CSS
  • Stripe Checkout / Portal / Webhooks (BRL)
  • Vercel (landing + dashboard)

Impact

Product outcome Live bot + panel + billing at dietaetreino.erbsu.com
Friction removed Log in Telegram; panel opens from a bot link
Privacy bar Groups opt-in; peers see aggregates, not meals
Commercial path 14-day trial → soft-block writes · R$29/mo

Logging stays in Telegram with no second install or login. Day macros, ~70-day consistency, and training volume open behind a short-lived link; peer comparison only after explicit opt-in. Billing follows trial → Checkout → soft-block while the bot stays the primary surface.

Learnings

  • Tuning who stays silent in a group chat took more iterations than swapping models.
  • Duplicated date logic plus a test was more reliable than a shared package we would not maintain.
  • Server Components and narrow types do most of the privacy work before the browser runs.
  • At this scale, structured events plus a weekly digest beat digging through raw logs for errors and latency.
  • Once the loop works, naming and landing copy still have to read as a product, without promising clinical accuracy.
  • Billing for a Telegram-first product is mostly access rules; Checkout should not ship ahead of trial and soft-block behavior.

Product snapshots

Live at dietaetreino.erbsu.com. Logging stays in Telegram; the panel opens from a bot link. Screens below are from the live product (Portuguese UI).

Telegram with Ana and Renan

Ask Ana about today’s macros (or Renan about training). She answers in chat and offers Ver no Dashboard when you want the full summary.

Telegram chat with Ana e Renan bot showing macro summary and Ver no Dashboard button
Private chat: day’s macros and a one-tap link to the panel. No extra login.

Summary and diet consistency

Dieta e Treino summary tab with greeting and calorie protein carb fat cardsDieta e Treino diet consistency heatmap for the last 70 days
Summary: estimated macros for the day, then the ~70-day diet consistency grid (same framing as contribution calendars).

Training progress

Dieta e Treino training tab with workout consistency heatmapDieta e Treino training volume by muscle group and cardio volume section
Training: consistency calendar, then strength volume by group and cardio volume. Empty states point back to Telegram to log.

Groups and peer progress

If you authorize Telegram groups in the bot, the Groups tab lists those chats and shows each member’s diet and workout consistency side by side: the same heatmaps as your own view, plus safe aggregates so you can see who is consistent or falling behind; not the full text of someone else’s meals. Opt-in is explicit (never automatic).

Dieta e Treino Groups tab explaining opt-in ranking and privacy for peer comparison
Groups: peer comparison only after each person opts in on Telegram; aggregates only, never another person’s meal text.

Subscription

Dieta e Treino subscription screen with monthly and annual plans during 14-day trial
Subscription: R$29/month or R$290/year during the 14-day trial, with Stripe Checkout and a portal for later changes.