A ticketing system for an iiko dealer, covering service and retail. One address serves both the web app and the mini app inside Telegram.
A company with two arms — service and retail. Tickets lived in chat threads: a broken till, an out-of-date price list and a request to visit a site all sat in one conversation, mixed together. There was no place where a task had a deadline, an owner and a history.
The client works out of Telegram and had no intention of leaving it. So the mini app is the main entrance and the website is secondary: the same address, the same database, and no separate build for the messenger.
Six states — new, in progress, deferred to a date, awaiting reply, cancelled, resolved. Three priorities, project blocks, several assignees, links between tasks, and deadline reminders that repeat.
A thread inside each task, files up to 25 MB, around forty formats on an extension allowlist, and an unread counter. The history stays with the task rather than in a chat someone has scrolled past.
One dictated sentence becomes a draft: who it is for, what to do, by when, how urgent and under which block. A person checks it and creates the task.
A message with a button that opens the task straight in the mini app. Events are picked with checkboxes on each task and frequent messages are merged — the bot does not turn into spam.
Groups with checkboxes instead of numbered roles: the owner creates their own. Visibility has three steps — your own tasks, your department, the whole company.
The work plan as a Gantt chart: dependency arrows, a “today” line, grouping by project. Alongside it, analytics — day-by-day trends, breakdowns by person and block, overruns. Refreshed every fifteen seconds.
The concept mockups the project began from: how the task card and the plan were imagined before the first working screen existed.
And these are screenshots of the running system, not drawn mockups. The web app and the mini app are built from one codebase: what you see here opens both in a browser and inside Telegram.
Rules and dictionaries instead of somebody else’s API. It understands inflected names, “by tomorrow, before 3pm”, “by Friday”, “in two hours”, “15 August”, plus priority and block. Masculine and feminine forms are told apart by case, so a task for Aleksandra Volkova does not go to Aleksandr Volkov. Zero cost per ticket and no dependence on anyone else’s uptime.
Whisper was benchmarked on the production hardware — two cores, no GPU. Small: 12 seconds per phrase. Medium: 32. Large-v3-turbo: 30. The transcribed text was identical. I kept small and wrote the measurements into the README, so the next person does not overturn the decision blind.
The server answers in 0.4–0.6 seconds, and you can feel it. Sections are cached for the session: returning to a tab paints instantly and fresh data follows. On a first open a placeholder holds the space, so the page height does not jump under the cursor.
I ran the chart palette through a validator: in the dark theme, red and green sit at ΔE 3.9 under colour blindness — an overdue task and a resolved one are indistinguishable. Overruns got hatching, and the status is repeated in words everywhere it appears.
Deployed to a production server over HTTPS. The client runs real tickets through it and gets notifications in Telegram.