2026 · Design + engineering
Deutsch mit Seele
School CRM inside Telegram — leads, conversations, broadcasts and analytics in one Mini App

Context
A private German-language school run by one teacher. Everything used to live in her personal chats: enquiries, level tests, trial-lesson requests, price questions — scattered across conversations, with no way to see who was still waiting for an answer. The product is a client-facing bot in four languages backed by a fullscreen Telegram Mini App: a lead CRM with folders, statuses and tags, a full conversation history where replies go out under the bot's name, notes, scheduled and recurring broadcasts, an editor for every piece of bot copy, and a funnel dashboard. Design, frontend, backend, database and handover to the owner came out of one set of hands.
Task
Build a working business system for someone who is not technical and who runs it entirely from a phone. Every screen has to survive a 320-pixel viewport inside Telegram's own chrome. The owner has to be able to change any word the bot says — in four languages, without a developer and without a deploy. Broadcasts have to reach the whole audience without tripping Telegram's rate limits or the platform's serverless time limits. And the bot itself has to feel personal: a level test that accepts answers as text, voice or video, encouraging replies while it waits, and requests that arrive as structured leads instead of loose messages.
Engineered
Next.js 16 + React 19 + TypeScript on Vercel, grammY for both bots, Postgres on Neon with Drizzle ORM and migrations, Zod on every boundary, Tailwind v4 design tokens, TanStack Query in the panel. Webhook ingest is idempotent — Telegram retries on timeout, so a dedup table keeps a lead from being answered twice. Broadcasts run through an Upstash QStash queue in chunks paced under Telegram's throughput ceiling, against a recipient snapshot taken at launch, so nobody who writes mid-run catches a stray message; recurring sends are cron rules with an honest note about daylight-saving drift. Media never touches storage of our own: files are relayed through a private Telegram channel, because a file_id belongs to the bot that uploaded it — the same constraint that makes a video note arrive as a square video unless it is re-uploaded with the right method. Bot copy lives in the database behind a sixty-second cache with a compiled-in fallback, so an edit reaches the bot within a minute and a broken database never leaves the bot mute. The panel is a fullscreen Mini App: initData signature check, owner and admin roles, safe-area handling, light and dark themes with seven accents, voice recording and attachments sent under the bot's name.
The client-facing side, in four languages. Tap through the menu the way a student would — the copy is the real thing, editable by the owner from the panel.