← All Projects

NutriKor

A nutrition diary that lives in Telegram. Send the bot a photo, a voice note or a line of text; it becomes a meal you confirm, then a day, a week and a trend.

Today screen with 1,756 of 2,650 kcal eaten, protein, fat and carbohydrate bars and a dinner draft waiting for confirmation
Dinner draft sheet listing salmon, potatoes and salad with editable grams and buttons to record, correct or delete it
  • 189

    n8n workflow nodes replaced by one service

  • 3

    ways to log a meal: photo, voice, text

  • 6

    interface languages

  • 1,100+

    automated tests

Client
KorLab, our own product
Platform
Telegram bot and Mini App, light and dark
Languages
English, German, Polish, Ukrainian, Belarusian, Russian
Our part
Product, design, agent, backend, Mini App
Timeline
n8n prototype, rebuilt on NestJS in 2026

The brief.

Context

NutriKor is a nutrition diary for people who train for a result, whether that means bulking, cutting or holding weight. Food goes in through the Telegram chat. The Mini App, opened from the same chat, turns those entries into a readable day, weekly reports and targets that change by period. It is our own product, from the brand to the deploy pipeline.

Challenge

The first version was a 189-node n8n workflow. A meal waiting for confirmation lived only in the agent’s eight-turn conversation buffer, so it vanished after a few messages or a restart. The Confirm button carried the bare word “confirm” with no draft id, so tapping an older message could save whichever meal was still in the window.

Approach

We rebuilt it as a NestJS service on App Engine. A draft is now a Firestore document with a stable id, and that id travels inside the button. Nutrition comes from USDA FoodData Central, then Open Food Facts, then an explicit not found, so the agent never makes up a calorie count. The Mini App reads the same data through a small REST API.

Photo, voice or text in. A draft out.

There is no form to fill in. You send the bot a photo of the plate, a voice note or a line like “salmon, potatoes, salad”. The agent splits the meal into parts, estimates each portion and looks up the figures per 100 g. The result waits as a draft until you confirm it, correct the grams or delete it.

  • Foods you log go into a personal product book, marked as verified, a reference or your own figures.
Today screen with 1,756 of 2,650 kcal eaten, protein, fat and carbohydrate bars and a dinner draft waiting for confirmation
Today
Dinner draft sheet listing salmon, potatoes and salad with editable grams and buttons to record, correct or delete it
Draft
Personal product book with seaweed salad, cottage cheese and crab sticks, each marked as a reference or own figures
Products

From one day to a week you can read.

Today shows calories and macros against the target and what is left. Reports average the last 7 or 30 days. Insights compare the week with the one before and end on one suggested next step.

  • A new target opens a new period from the day you choose. Past days stay measured against the target that was in force then.
Seven-day report averaging 2,573 kcal a day, with calories by day and a protein, fat and carbohydrate stack
Report
Weekly insights titled Better than last week, with a seven-day strip of green days and one suggested next step
Insights
Goals screen with the target in force since 20 September and a past period from 24 July to 19 September
Goals

Friends, green days and levels.

Friends share a weekly board with a score out of 100 for each day. Seeing someone’s diary is a separate request they approve. Each of the four targets met at the end of a day is a green day and earns 1 XP, so a day is worth up to 4. Levels follow from XP.

Friends board for the week with daily scores out of 100, a friend request and a diary access request
Friends
Level-up card for level 7 with green days counted for calories, protein, fat and carbohydrates
Level up

A button that confirms the right meal.

The n8n version broke on a Confirm button that did not know which meal it belonged to. Now the draft id is part of the button’s payload. A tap three days later finds exactly that draft and files it on its own date. The saved meal takes the draft’s id, so a second tap changes nothing.

  • Day totals are updated in the same Firestore transaction as the meal.
  1. Telegram

    A photo, voice note or text reaches the webhook. Voice notes are transcribed first.

  2. Agent

    A tool-calling loop of at most eight rounds splits the meal and asks the nutrition tools for figures.

  3. Nutrition lookup

    USDA FoodData Central, then Open Food Facts, then an explicit not found. No guessed numbers.

  4. Draft

    Stored in Firestore with a stable id. The bot replies with buttons that carry that id.

  5. Diary

    Confirm saves the meal under the draft’s id and updates the day totals in one transaction.

Everything around the diary.

Around the diary sit the parts that keep it running: messages the bot sends on its own, a console that shows what the model costs, and a deploy that can undo itself.

  • Morning digest

    Every day at 06:00 UTC the bot sends a summary of the day before, with nudges for quiet users.

  • Spend ledger

    Every model and transcription call is recorded and reconciled daily against the OpenAI bill in a FireCMS console.

  • Canary deploys

    Lint, unit and end-to-end tests, a no-traffic App Engine version, a health check, then a traffic shift that rolls back on failure.

  • No keys in the repo

    Secrets load from Secret Manager at boot, and CI deploys through Workload Identity Federation.

  • One build, three hosts

    The same web build runs inside Telegram, in a browser and in a Flutter shell for iOS and Android.

  • Telegram Stars

    Voluntary support through Telegram Stars, with invoices, a ledger and refunds.

Calm, numeric, at home in Telegram.

The Mini App reads Telegram’s own theme, so it opens light or dark to match the chat it came from. Colour is kept for meaning: one per macro, green for a target met, amber when a day drifts. Numbers are large; everything else stays quiet.

  • Protein
  • Fat
  • Carbohydrates
  • Calories
  • On target
  • Drifting
  • Paper
Today screen in Telegram’s dark theme with the same day’s calories, macros and pending dinner draft
Dark theme
Seven-day report in Telegram’s dark theme with calories by day and the macro stack
Report, dark

What we built.

Our part

  • Product idea, brand and interface design
  • LLM agent and its nutrition tools
  • NestJS API with persistent drafts and day totals
  • Telegram Mini App in Vite and TypeScript
  • Flutter shell for iOS and Android
  • FireCMS admin with model spend tracking
  • CI/CD with canary rollout and automatic rollback

Stack

Mini App
  • Vite
  • TypeScript
  • Telegram Web Apps SDK
  • Flutter shell
Backend
  • NestJS
  • Firestore
  • Google App Engine
  • Firebase Auth
  • zod
AI and data
  • OpenAI tool calling
  • OpenAI transcription
  • USDA FoodData Central
  • Open Food Facts
Operations
  • GitHub Actions
  • Secret Manager
  • App Engine cron
  • FireCMS
  • Telegram Stars

Outgrowing your n8n workflow?
Let’s make it a product.

We rebuild no-code prototypes as services with real data models, tests and deploys. Tell us what yours does.