NataCoach / product & system design Wiki Brain Personas Coach Console ↗

02 — User Experience

How NataCoach feels to a client, hour by hour: invite, onboarding, the daily loop, the weekly rhythm, and every off-nominal path — all inside Telegram, all propose-confirm.

The prime directive from the brief is the user does less. Every flow below is designed against a hard interaction budget:

A normal training day Budget
Proactive messages from @NataCoachBot ≤ 4
Taps by the user ~8
Photos taken 2–4
Typing required 0 (always optional)
Screen time outside the workout < 6 min

If a design choice increases this budget, it is the wrong choice. See 01-product-vision.md for why.

1. Invite and onboarding (Day 0)

1.1 The invite

There is no public bot discovery in the pilot. Nata sends each client a personal invite link from her own Telegram account — the human handoff matters: "I built something so I can coach you every day, not just at sessions. Tap this." The link is a deep link generated in the Coach Console: https://t.me/NataCoachBot?start=inv_a7f3k2 — single-use, expires in 7 days, and carries the profile Nata pre-filled (name, goal sketch, draft program). So the very first bot message already knows who you are.

1.2 Conversational intake (~10 minutes)

Onboarding is a conversation, not a form. Rules: one question per message, every question answerable by tapping a chip (free text always allowed), every step skippable with [ Skip for now ] (the bot circles back within the first week). Total time ~10 minutes.

Step What the bot asks Capture Seeds Wiki Brain page
1. Welcome Sets expectations: "10 minutes, mostly taps" — and states the coaching model plainly: "You're coached by Nata through this bot. AI drafts, Nata supervises everything — and sometimes it's literally her typing." wiki/profile.md (from invite token)
2. Goals Primary + secondary goal chips chips + free text wiki/goals.md
3. Injuries / contraindications "Anything I must know before we load weights on you?" free text encouraged, never skippable silently wiki/constraints-injuries.md
4. Equipment & venue Gym / home / hotel; what's available chips wiki/profile.md (equipment)
5. Schedule Training days, preferred slots, wake/sleep pattern; timezone auto-detected (Mini App Intl API, cross-checked against the wearable's sleep-record UTC offset) and confirmed with one chip chips + time picker wiki/preferences.md (drives notification windows)
6. Food habits Typical day of eating, who cooks, allergies, alcohol chips + free text wiki/nutrition-patterns.md (seed)
7. Permissions & health-data consent Consent for Meal Lens photos and Form Check videos (seen by user + Nata only) plus explicit GDPR Art. 9 consent for wearable health-data ingestion, contraindication storage, and LLM processing — per 03 §7, captured before any Health Sync connection or photo processing explicit [ I agree ] wiki/profile.md (consent flags)
8. Health Sync connect Whoop or Garmin OAuth, in-flow deep link wiki/recovery-patterns.md (baseline)

The two consent moments, verbatim (step 1 and step 7):

NataCoachBot:
Two agreements before we start, in plain words:

1) You're coached by Nata through this bot. AI drafts, Nata
   supervises everything — and sometimes it's literally her typing.
2) To coach you I process health data: your wearable's sleep and
   recovery, meal photos, training videos, and anything you tell me
   about injuries. Stored encrypted, seen only by you and Nata,
   never used to train models, deleted on request (/delete_my_data).

[ I agree — let's go ]   [ Ask a question first ]

A representative excerpt (Marta, step 2–3):

NataCoachBot:
Hi Marta — Nata told me about you, so this will be quick.
Ten minutes, mostly taps, and I handle the rest.
First: what are we training for?

[ Get stronger ]  [ First pull-up ]  [ More energy ]  [ Type my own ]

Marta: taps [ First pull-up ], then [ More energy ]

NataCoachBot:
A pull-up and more energy — noted. Nata already sketched a
3×/week program for exactly that.
Now the one question I take most seriously: anything I must
know before we load weights on you — injuries, surgeries,
doctor's advice? Free text is welcome here.

[ Nothing to flag ]  [ Let me type ]

Marta: taps [ Let me type ]
Marta: c-section 8 months ago, cleared for training.
       lower back gets cranky sometimes

NataCoachBot:
Thank you — that goes into your file as a hard rule: we
rebuild your deep core deliberately, and any back pain is a
stop sign, not a "push through". Nata sees this too.

Step 3 answers are written to the Wiki Brain as ground-truth constraints and surfaced to Nata for program sign-off — see 08-llm-wiki-brain.md and the safety rails in the brief.

1.3 Health Sync connect, inside the flow

No "go to settings later". The OAuth happens in the same conversation via deep link (mechanics in 04-data-collection.md):

NataCoachBot:
Last thing: your Whoop. Connect it, and every morning plan
starts from how you actually slept — not how you were
supposed to.

[ Connect Whoop ]  [ Connect Garmin ]  [ Later ]

Marta: taps [ Connect Whoop ]
→ Whoop login opens in Telegram's browser → "Authorize NataCoach"
→ redirected back into the chat

NataCoachBot:
Connected. I can already see last night: 6 h 48 m sleep,
recovery 61%. Your first Morning Brief lands tomorrow,
30–45 minutes after you wake. That's it — you're done here.
Nata reviews your program tonight; tomorrow we start.

The first data pull is echoed back immediately ("I can already see last night") — proof the connection worked, and the first small moment of being seen.

2. The daily loop

2.1 A full training day, end to end

flowchart TD
 A["Overnight: Health Sync ingests sleep + recovery"] --> B["07:40 Morning Brief"]
 B --> C{"Recovery band"}
 C -->|"green (67–100%)"| D["Plan as written"]
 C -->|"yellow (34–66%)"| E["Trimmed plan: volume −10–20%"]
 C -->|"red (1–33%)"| F["Swap proposed: light day or rest"]
 D --> G["One tap: Looks right / Adjust / Rest instead"]
 E --> G
 F --> G
 G --> H["08:50 Breakfast photo → Meal Lens reply < 60 s"]
 H --> I["12:15 Pre-workout nudge"]
 I --> J["12:30 Session Mode: per-set cards, rest timers, RPE taps"]
 J --> K["13:15 Finish summary + recovery-meal hint"]
 K --> L["Lunch / dinner photos → Meal Lens"]
 L --> M["20:45 Evening close: day recap + tomorrow preview"]
 M --> N["Quiet hours 21:30–07:30: zero proactive messages"]
 N --> O["03:00 Nightly distillation updates Wiki Brain (invisible)"]

2.2 Morning Brief

Lands 30–45 minutes after detected wake (from the wearable); if no wake signal arrives, it falls back to the user's chosen time (default 07:15 local) — never inside quiet hours. (The brief itself is built by a per-user pre-dawn job, 03 §2; 04 §6 states the same contract.) It always does three things in one message: (1) reads back last night in one line, (2) proposes today's plan — already adjusted for recovery, (3) offers exactly three buttons. Recovery bands (Whoop convention; Garmin Body Battery mapped equivalently — see 04-data-collection.md):

Band Reading Default proposal
Green 67–100% recovered Plan as written; progression allowed
Yellow 34–66% partial Same session, volume −10–20%
Red 1–33% run down Swap: light/mobility day or rest

Transcript — Marta, Morning Brief + meal photo (Tue):

── Tue 07:41 ─────────────────────────────────────────

NataCoachBot:
Morning, Marta. Whoop says recovery 31% — 5 h 12 m sleep,
HRV 38 ms against your 52 baseline. Rough night with the
little one?

Today was Pull Day B. My proposal: keep the session, cut
volume 20% — 3 working sets instead of 4, same weights.
You still move toward that pull-up without digging the
hole deeper.

[ Looks right ]  [ Adjust ]  [ Rest instead ]

Marta: taps [ Looks right ]

NataCoachBot:
Done — Pull Day B (light) is loaded for your 12:30 slot.
I'll ping you 15 minutes before.

── 08:52 ─────────────────────────────────────────────

Marta: [photo: syrniki with sour cream and blueberries]

NataCoachBot:
Syrniki with sour cream and blueberries — good morning
indeed. My estimate:
~430 kcal · 27 g protein · 41 g carbs · 16 g fat

[ Looks right ]  [ Adjust ]

Marta: taps [ Looks right ]

NataCoachBot:
Logged. Protein so far: 27 / 110 g. The cottage-cheese base
is doing the real work here — exactly right for a red-
recovery day. If you're hungry before training, a glass of
kefir tops this up without sitting heavy.

2.3 Meal Lens moments — photo to feedback in under 60 seconds

The reply is deliberately two-stage, which is how we reconcile "instant feedback" with Coach-in-the-loop approval (full pipeline in 05-food-analysis.md):

Stage Content Latency target
Ack "Got it — reading your plate…" < 2 s
Macro card Dish name + estimate + [ Looks right ] [ Adjust ] < 20 s
Coach comment Feedback relative to Nata's food program, in Nata's voice < 60 s total

In the early pilot the coach comment passes through Nata's approval queue (her median approval: ~20 s during active hours); as the autonomy dial moves to auto-send with audit, the queue wait disappears entirely. Macros are always labeled estimates.

sequenceDiagram
 participant M as Marta
 participant B as NataCoachBot
 participant W as Meal Lens worker
 participant L as Claude vision
 participant N as Nata via Coach Console
 M->>B: meal photo (08:52:10)
 B->>M: ack "reading your plate" (t+2 s)
 B->>W: enqueue meal_photo job (BullMQ)
 W->>L: photo + food program + Wiki Brain context
 L-->>W: dish, macro estimate, draft coach comment
 W->>B: macro card
 B->>M: "~430 kcal · 27 g protein…" + buttons (t+18 s)
 M->>B: taps "Looks right" (t+31 s)
 W->>N: draft comment enters approval queue
 N-->>W: approve (median ~20 s)
 W->>B: comment through persona layer
 B->>M: coach feedback in Nata's voice (t+52 s)
 Note over W,N: Autonomy dial later: auto-send with audit, no queue wait

2.4 Session Mode

The pre-workout nudge arrives 15 minutes before the scheduled slot: [ Start session ] [ Push 1 h ] [ Skip today ]. Tapping [ Start session ] runs the session as per-set cards in chat (a Mini App runner with the same cards is one tap away for people who prefer a full screen — see 06-training-experience.md). Each card: exercise, proposed weight × reps from the progressive-overload engine (history + today's recovery), a rest timer, and two buttons. Effort is captured once per exercise, after the last set — not after every set.

Transcript — Marta, mid-workout set card:

── Session Mode · Pull Day B (light) · 12:41 ─────────

NataCoachBot:
Exercise 2 of 5 · Lat pulldown — set 2 of 3
Proposal: 35 kg × 8
(Last time 35 kg × 8 felt 🟢 easy — normally I'd move you
to 37.5, but recovery is red today, so we hold.)

[ Done as proposed ]  [ Adjust ]

Marta: taps [ Adjust ]

NataCoachBot:
Weight 35 kg  [ −2.5 ]  [ +2.5 ]     Reps 8  [ −1 ]  [ +1 ]

Marta: taps [ −2.5 ], then [ Save 32.5 kg × 8 ]

NataCoachBot:
Logged 32.5 kg × 8. Rest 90 s — timer running.

── after set 3 ───────────────────────────────────────

NataCoachBot:
Last set done. How did lat pulldowns feel today?

[ 🟢 easy ]  [ 🟡 solid ]  [ 🟠 hard ]  [ 🔴 maxed ]

Marta: taps [ 🟠 hard ]

NataCoachBot:
Noted — red day doing red-day things. Next exercise:
seated cable row, and I've already trimmed the proposal.

The finish summary closes the session in one message: total volume (e.g. "4,230 kg moved, 92% of plan"), anything that was a PR, one recovery-meal hint tied to the food program, and [ Done ]. Everything logged lands as events; the Wiki Brain distills them overnight.

2.5 Evening close

Between 20:30 and 21:00 (always before quiet hours): a recap of the day — meals logged and protein vs target, training done or moved, one line of tomorrow's preview. If the day's data has an obvious hole, the close asks exactly one low-friction question: "I only saw two meals today — did I miss one?" [ All logged ] [ Add a meal ]. Then the system goes quiet, and the nightly distillation job (invisible to the user) files the day into the Wiki Brain per 08-llm-wiki-brain.md.

3. Weekly Review (Sunday)

Sunday ~18:00, one message: "Your week, in 90 seconds." [ Open Weekly Review ] opens the Mini App:

Block Content
Charts Weight trend (7-day average), protein adherence per day, sessions completed vs planned, recovery/strain overlay
One win Single concrete highlight, e.g. "First 3×5 chin-up negatives — the pull-up is coming"
One focus Single change for next week, never a list
Nata's voice note Real 30–60 s recording from Nata (she records all ~10 clients from a Console digest in ~15 min — see 09-admin-analytics.md)
Next week Proposed plan: [ Looks right ] [ Adjust ] [ Talk to Nata ]

The Friday weigh-in feeds this: the bot proposes the number from the trend — "Trend says ~87.4 kg. Step on the scale and confirm?" [ Confirm 87.4 kg ] [ Edit ] — so even the weigh-in is one tap on a good week.

4. Form Check, from the user's side

Any video sent to the chat is treated as a Form Check candidate; the bot also offers it contextually after heavy sets ("Want a Form Check on that last set next time? Film side-on."). Flow from the user's seat (pipeline in 07-video-feedback.md):

  1. User sends a video (one exercise, ≤ 60 s; the bot hints at the best camera angle per exercise).
  2. Bot confirms intent: [ Check my form ] [ Just sharing ], and acks instantly with an honest ETA.
  3. Feedback arrives within 4 waking hours in the pilot, per the SLA in 07 §3 (Nata approves every Form Check early on; usually much faster). Format is fixed: one thing done well + at most two fixes, sometimes with an annotated still frame. Never a wall of cues.
  4. The top cue follows the user forward: it reappears inside the relevant Session Mode set card next time ("Cue from your last Form Check: chest tall out of the hole").

Any mention of pain in the video or caption escalates to Nata immediately and pauses programming per the safety rails. Videos are visible only to the user and Nata, are never used to train models, and can be deleted on request.

5. Notification strategy

5.1 The proactive budget: max 4 per day

Slot When Days Counts
Morning Brief 30–45 min after detected wake (fallback: chosen time, default 07:15) every day 1
Pre-workout nudge 15 min before slot training days 1
Evening close 20:30–21:00 every day 1
Contextual (max one) as earned e.g. Friday weigh-in, Health Sync reconnect, hydration on a 16+ strain day 0–1

Reactive replies (to the user's photos, messages, session taps) are unlimited but never re-open a conversation more than 10 minutes after the user's last action. Rest days naturally run at 2–3 proactive messages, silence-ladder days at 1 or 0 (see 6.4). The budget is a ceiling, not a quota.

5.2 Quiet hours

Default 21:30–07:30 local, auto-tuned to the user's actual sleep window from Health Sync. On travel, the timezone updates from the wearable's sleep-record UTC offset or the travel-mode confirmation (§6.2) — Telegram itself exposes no phone timezone to bots, so we never rely on it. The rule is absolute: zero proactive messages in quiet hours, no exceptions — anything urgent (e.g. a worrying overnight signal) routes to Nata's Coach Console, not to a sleeping client.

5.3 Everything actionable: the propose-confirm micro-interactions

Every proactive message carries inline buttons; the leftmost button is always the one-tap happy path; [ Adjust ] always opens the smallest possible editor (steppers, not forms); and doing nothing never breaks anything — proposals expire gracefully.

Moment Proposal Buttons If no tap
Meal macros estimate from photo [ Looks right ] [ Adjust ] after 2 h the estimate is logged as confirmed: implicit (05 §3)
Today's plan plan + recovery tweak [ Looks right ] [ Adjust ] [ Rest instead ] plan stays loaded; folded into pre-workout nudge
Per-set load weight × reps [ Done as proposed ] [ Adjust ] session simply waits — user-paced
Exercise effort RPE after last set [ 🟢 easy ] [ 🟡 solid ] [ 🟠 hard ] [ 🔴 maxed ] logged 🟡 solid, flagged inferred
Friday weigh-in trend value [ Confirm 87.4 kg ] [ Edit ] skipped; trend keeps running
Travel swap hotel-variant session [ Do it ] [ Keep original ] [ Show circuit ] original stays scheduled
Next week's plan Sunday draft [ Looks right ] [ Adjust ] [ Talk to Nata ] Nata pinged Monday morning

6. Off-nominal days

6.1 Rest days

The Morning Brief still arrives but shrinks to two lines: the recovery read plus, on green days, an optional offer — [ 10-min mobility ] [ Pure rest ]. No pre-workout nudge. The evening close mentions protein only if the day is trending short. Rest is presented as part of the program, never as an empty day.

6.2 Travel mode (Denys)

Triggered by the user saying so, or by the bot noticing a wearable timezone jump and asking. Effects: sessions swap to the hotel/bodyweight variants Nata pre-authored, restaurant meals can be described instead of photographed, zone-2 degrades to a step/heart-rate target when there's no gym, and all notification times shift to local time.

Transcript — Denys, travel-day adaptation (Mon, Berlin):

── Mon 07:55 · Berlin ────────────────────────────────

NataCoachBot:
Morning, Denys. Garmin says you woke up in a new timezone —
Berlin for the week?

[ Yes, until Fri ]  [ Just a layover ]  [ Edit dates ]

Denys: taps [ Yes, until Fri ]

NataCoachBot:
Travel mode on until Friday. Straight talk: travel weeks
are where 96→88 usually stalls, so we plan for the hotel
you have, not the gym you don't.

Today was Strength A (barbell). Swap: 35-min dumbbell
circuit — goblet squats, floor press, one-arm rows, farmer
carries. Wednesday's zone-2 stays: 40 min at 130–138 bpm,
the river path by your hotel works.

[ Do it ]  [ Keep original ]  [ Show circuit ]

Denys: taps [ Do it ]

── 19:40 ─────────────────────────────────────────────

Denys: no photo tonight, client dinner. italian place

NataCoachBot:
No photo needed. Tell me roughly what you had.

Denys: beef carpaccio, tagliatelle with ragù, 2 glasses red

NataCoachBot:
Estimate: ~1,150 kcal · 52 g protein · 88 g carbs ·
55 g fat (the wine is ~180 kcal of that).

[ Looks right ]  [ Adjust ]

Denys: taps [ Looks right ]

NataCoachBot:
Logged. Honestly? A fine travel dinner — the carpaccio
carried your protein. Day lands ~2,350 kcal against your
2,200 target: a nudge, not a derail. Tomorrow's brief will
propose a protein-heavy breakfast and your zone-2 before
the 10:00 meeting. Deal?

[ Deal ]  [ Adjust tomorrow ]

6.3 Sick and pause modes

Entering: the user says they're ill, taps [ Need a pause ], or the bot offers it from the data — e.g. "Whoop shows respiratory rate up 2.1 breaths/min over baseline and recovery 22%. Feeling okay?" [ I'm fine ] [ Feeling off ]. In sick mode: programming stops immediately, Meal Lens stays available but goes silent on adherence, and the only proactive message is a 48-hourly check-in — [ Better ] [ Same ] [ Worse ]. Two Worse taps or anything medical-adjacent escalates to Nata with a "please see a doctor" deflection, per the safety rails. Returning: the first session back is proposed at ~85% of previous loads with reduced volume — the ramp is proposed, never asked for. Pause mode (vacation, life) is simpler: a resume date, then full silence until it.

6.4 Going silent: the re-engagement ladder

When a user stops responding, the system escalates humanity, not volume — messages get fewer and more human, never louder.

Silence System behavior The message
24 h Budget drops to Morning Brief only, shortened "Short version today: recovery 58%, plan's loaded whenever you want it."
48 h Everything muted except one one-tap check-in "No coaching today — just one tap: how are you? [ All good ] [ Rough patch ] [ Need a pause ]"
72 h Bot goes fully quiet; alert fires in the Coach Console Nata sends a real personal message or voice note — hers, informed by the Wiki Brain summary the Console shows her
7 d Human decision, not automation Nata calls, pauses, or offboards

When the user comes back, there is no guilt and no backfill homework: "Good to see you. Pick up where we left off, or restart light?" [ Pick up ] [ Restart light ]. Missed days are simply absent from the record — the Wiki Brain notes the gap; nobody is asked to reconstruct it.