HealthIOS

Visual app tutorial — how each tab, card, and flow works.

iOS 26 · SwiftUI · SwiftData + HealthKit + Supabase + GH · Last updated 2026-05-20

CORE GOAL

Większe adherence + większe consistency — żeby chciało mi się ćwiczyć. Każda feature filtruje się przez 5 kryteriów: Friction reduction · Failure-proof · Identity reinforcement · Variable reward · Minimal Effective Dose.

Banned shame language: missed / failed / didn't / must / should / behind pace.

Contents
  1. Tab structure
  2. Today — daily anchor
  3. Train — workout session phase machine
  4. Food — meals + drinks
  5. Progress — trends + body
  6. Plan — capacity + progression
  7. Hidden systems — Coach, MED, week boundary
  8. Glossary
  9. Supabase free tier budget

1. Tab structure

4 tabs. Plan + Settings open via fullScreenCover (iOS 26 hidden Tab quirk workaround).

Today
Anchor card + quick logs + nudges
Train
Workout session, camera, HUD
Food
Meals, drinks, macros
Progress
Trends, body comp, deep dives

Toolbar (top-right of every tab):

2. Today — daily anchor

Najczęściej otwierana page. Zaprojektowana jako "1-tap from intent to action".

Today Tuesday · May 20 Move · Exercise · Stand · Steps Promise card · 14:00 walk JustDoSomething · 1 set zero-friction Wellness sliders ●●●●○ Mood · Energy · Sleep · Stress ▣ Log pain / discomfort → Quick log · meals Drinks ☕ ☕½ ☕ Yerba Caffeine 80/300 mg 📓 Week reflection · 2 min → Apple Fitness rings Move/Exercise/Stand/Steps Promise card Cialdini commitment + UNCalendarTrigger reminder Just Do Something MED (minimal effective dose) Pain map 18 tap zones · severity 1-10 Drinks + caffeine Time-aware sleep impact Weekly reflection Friday eve + Saturday only

Today cards — top to bottom

Hero4-ring stack

Move · Exercise · Stand · Steps from HK. Auto-refresh przy app foreground.

PromisePromise card

1-tap promise dla future moment ("14:00 — short walk"). Schedules UNCalendarTrigger notification. Stays active commit-day + execution-day.

MEDJustDoSomething

1 zero-friction action gdy "nie chce mi się". Minimal effective dose — 1 set, 60s walk, 1 stretch. Failure-proof.

ReflectWellness sliders

4 sliders (mood/energy/sleep/stress 1-5). Feeds ReadinessEngine → Coach. ~10s log.

PainPain map sheet

Body diagram 18 tap zones (head→feet, bilateral). Severity 1-10 + note. Stored UserDefaults JSON (50 max). For transient/positional pain HRV nie wychwytuje.

DrinksDrinks quick log + budget

4 presets: Espresso, ½ kubka, Pełny kubek, Yerba (czas + mg caffeine). CaffeineBudgetCard pokazuje cap 300mg + cut-off 14:00 + post-cutoff sleep impact estimate.

StreaksHabitStreaksStrip

Tygodniowe streaks (Workouts ×/wk, Walk min, etc.). Sat-Fri week boundary.

PrincipleDailyPrincipleStrip

Rotating quote z Outlive (Attia) / Built To Move (Starrett). Daily anchor identity.

ReflectionWeekly reflection

Self-gated card — Friday 18:00+ / Saturday only. 3 prompts (worked / friction / next 1%). Stored UserDefaults JSON (12 max). Atomic Habits weekly review.

IdentityIdentityGoalCard

Collapsed: rotating identity statement per weekday (variable reward). Expanded: 4 goal layers (longevity/recomp/feel-good/consistency) z principle quotes.

HabitsHabitsInventoryCard

User-defined aspirational habits — 1-tap check, 7d adherence %. Hidden gdy empty. Manage sheet z 8 evidence-based suggestions (Outlive / Atomic Habits / Built To Move).

CameraCameraQuickStartCard

1-tap launch: Push-ups / Squats / Pike push / Diamond → Train tab + camera + recording. Pain-aware: gdy region pain ≥5 logged today, preset z red border + "⚠ pain logged today" subtitle.

Pain v3Multi-region pain + status button

Chip toggle z per-region severity memory (Dictionary draft). Slider per chip → "Log all (N)" naraz. "All good today" baseline (severity 0 = green). 6 self-check protocols expandable. Dynamic Today button: idle / draft (orange badge N) / recent (gray + most-flagged region).

TrendsPainTrendCard (Progress tab)

30d severity scatter chart (SwiftCharts) + per-region stats (count, max, recent, when). All-clear days counted separately. Chronic vs transient pattern recognition.

EditEditMealItemSheet

Tap ingredient w AddMealSheet → modal edit grams + macros + name. Auto-scale macros proportional (toggle ON default). "Reset to original" + per-field "orig:" reference labels.

StatusTodayStatusStrip

Glanceable pills pod date label: habits X/Y · 🔥N streaks · workouts X/Y wk. Hidden gdy zero data.

At-riskHabits loss-aversion

Habit z streak ≥3 + nieukończony + ≥18:00 → orange "at risk" badge + red flame + orange background. Cialdini consistency trigger.

★ AdaptiveQuick-log preset badges

DrinkQuickLog + CameraQuickStart — most-tapped preset w last 14d dostaje ★ yellow badge + thicker border. NO reorder (muscle memory zachowany). Threshold: 3+ taps total dla DrinkQuickLog, 2+ launches dla camera. Pain alert priority overrides star.

Coach contextEngagement signals do LLM

CoachAdvisor.buildEngagementLines reads UsageAnalyticsStore last 7d → top 3 dwell cards + peak hours feed do system prompt. Coach może reference: "noticed habits card holds attention, let's lean on tomorrow's commitment" lub "your 07:00 active window — schedule mobility there".

Context promptsAskCoachSheet quick prompts

Static 4 presets + 1-3 dynamic context-aware: recent pain (severity ≥4 w 24h) → "Modify today's plan?"; past 14:00 cutoff + caffeine logged → "Sleep timing impact?"; Friday eve / Saturday → "Recap last week + 1% nudge?".

DiagnosticSkeleton upload status

Settings > Recordings > toggle pokazuje "Last: ✓ Sent 87 KB · 14:23" lub "⚠ Skipped: no frames captured · 14:23" — debug bez Xcode console attach.

LoggerIn-app debug logger

Settings > App > "App logs (debug)" — real-time tagged feed (NSLock thread-safe). Auto-push do Supabase app_logs table every 5s. Claude może query: scripts/sb "SELECT * FROM app_logs WHERE ts > NOW() - INTERVAL '1 hour'".

BG uploadURLSession.background (survives lock/kill)

Recording upload via URLSessionConfiguration.background. Phase A retry on scenePhase.active + Phase B true-background survives screen lock + app suspend + nawet app kill (iOS resumes). Multipart body → tmp file → uploadTask(fromFile:).

Test planLive URL z TODO list

health-dashboard.f1th4p.workers.dev/test?token=... — top-of-page "📌 Co musisz zrobić TERAZ" z 5 numbered priority actions + 18+ ready-to-test items. Updates per commit (60s CDN cache).

Hub bridgeiOS → Hub workout_meta + ios_skeleton

Recording upload teraz attaches: ios_skeleton (30fps gzipped keypoints) + workout_meta (exercise slug, target_sets/reps, AMRAP flag). Hub uses dla calibrated pose detection + form verdict context.

Coach deep-linkAskCoachSheet initialQuery prefill

3 sites reuse pattern: CapacityBuckets missing/under tap, Pain chronic bubble, Habits long-press → AskCoach z context-aware query. LLM dostaje rich state info bez user typing.

Time bracketToday greeting (time-aware)

Header: "Morning, Bartek" / "Late morning — peak focus" / "Evening wind-down" / etc. Matches CoachAdvisor time-bracket signal — consistent UX↔LLM phrasing.

Pain chronicPattern detection (14d)

Gdy region zalogowany ≥3× w 14d z avg severity ≥4 → PainLogStatusButton zmienia state na "Pattern: Left knee ×4 (avg 5.5/10)" red tint + waveform icon. Coach context gets "⚠ Chronic pattern" line → suggest exercise modification + PT consult escalation.

Habit packsStarter packs (1-tap × 3)

HabitsInventorySheet: 3 themed bundles (Sleep / Recovery / Mind) — tap = adds 3 habits at once z dedup. Reduces empty-state friction dla first-time setup.

Meals smartAuto re-parse + Combos

Legacy entries (itemsJSON=nil): composite fallback (0ms) → async LLM split (2-5s) replaces z proper breakdown. "Often together" combos detect co-occurring item pairs ≥3× in 30d → 1-tap clone pack.

Watch habit1-tap habit check z Watch

Apple Watch "Habit ✓" button → iPhone toggles primary pending (highest-streak unchecked). WCSession message z empty sentinel, iPhone resolves target habit.

Today adaptiveCards reorder by dwell (14d)

Quick-actions section (Drink, Camera, Caffeine) sortowane by total dwell time. Most-engaged surfaces first. Cold-start = default order (Drink→Camera→Caffeine) gdy <10 events.

Time contextCoach time-bracket awareness

Time-of-day signal → Coach LLM: "Late morning (peak focus — heavy training OK)" / "Late evening (sleep prep — no caffeine)" — 7 brackets. Suggestion style matches current hour bez location permission.

3. Train — workout session phase machine

Source: WorkoutSessionViewModel.swift

.idle .set(n) .rest(n, remaining) .done Start completeSet if remaining=0 if n=targetSets → .done End → back to .idle

Phase changes drive: HUD overlay, camera + pose overlay, voice cues (VoiceCue.speakSetComplete), recording (.set → start, .rest → save), HR stream, AMRAP timer, tab bar hide.

Quick-start pills (idle phase)

Mobility Posture AMRAP ♫ Music

Music pill = music:// deep-link → Apple Music. AVAudioSession .ambient + .mixWithOthers = muzyka pod Voice cues bez ducking.

4. Food — meals + drinks

Add meal flow:

  1. Tap "+ Add meal" → AddMealSheet
  2. Camera (photo) OR text entry ("kurczak ryż brokuły")
  3. LLM analiza (Gemini/LM Studio) → kcal + protein/fat/carbs
  4. Save → MealEntry SwiftData + push do GH (log/MM-DD.md "## Posiłki" section)

Drinks quick log = sub-class meals, dedicated card na Today bo "1-tap kawa" >> 5 tap "add meal → coffee → save".

5. Progress — trends + body

Hero metric

Body weight 7d / 30d trend z arrow direction. Tap → TrendDetailSheet z LLM analysis.

Form deep dive

Per-exercise: dynamic frame count (2-6) based na reps_estimate. Frames URLCached (50MB mem / 200MB disk).

Body composition

BIA values (weight + lean + fat %). NIE alarmuje LBM zmian w pierwszych 2-3 tyg recomp (BIA noisy).

Goal progress bar

Toward goal weight, deadline-aware. Locale en_US (Apr nie Kw).

6. Plan — capacity + progression

Sources of plan suggestion:

7. Hidden systems

Coach v3 (LLM-powered)

CoachAdvisor + CoachDigestEngine build context z:

Daily digest fired post-9pm → Notification z 1-sentence "what worked, what next". Tap → AskCoachSheet.

Sat-Fri week boundary

App używa Saturday jako start-of-week (cal.firstWeekday = 7). Reason: weekend treningi Bartka — wk start Sat = "świeży start", Friday = "reflection day". 3 miejsca w code: HabitStreaks, CoachAdvisor, ReadinessEngine.

Friction reduction patterns

1-tap Drinks (4 presets), pain log, promise quick set
MED JustDoSomething card — never zero, just something
Pre-filled RPE chips 6-10 w QuickWorkoutLogSheet (no typing)
No nav All key actions w 1-2 taps from Today

Network resilience

8. Glossary

CORE GOALAdherence + consistency. Wszystko filtruje się przez 5 kryteriów.
MEDMinimal Effective Dose. 1 set, 60s walk. Failure-proof.
5 filtersFriction / Failure / Identity / Variable / MED.
PromiseCialdini commitment device — schedule action + reminder.
AnchorBJ Fogg tiny habit — daily fixed-time tiny action.
Catch-upSat-Fri week remaining sessions to hit goal.workoutsPerWeek.
RPERate of Perceived Exertion (Borg CR10, 6-10). Drives PlanAdaptation.
Park bench / Bus stationDan John recovery-driven session intent.
GtGGrease the Groove (Pavel) — frequent low-intensity volume.
Capacity bucketsAndy Galpin 7 fitness qualities.
Sat-Fri weekApp week boundary. firstWeekday=7.
Audit simDrugi headless iPhone sim (F66A3F1E) — debug pisze tam, nie do user'a (1EC11912).
Dual deployKażda zmiana → sim.sh + install.sh równolegle (visual + functional verify).

9. Supabase free tier budget

Live calculator dla projected DB usage. Wszystkie dane health-ios trafiają do jednego Supabase projektu (xctrcwunonuggrgnlggw).

Free tier limits

Database500 MB
Egress5 GB / month
API requestsunlimited
Storage (files)1 GB

Projected usage — adjust inputs ↓

Formula: row_size × rate/day per table → suma → (limit − fixed_baseline) / yearly_growth = years runway. Row sizes empiryczne (include index overhead ~2×). Egress dominuje storage usage tylko jeśli dashboard heavy-fetched — read pattern niski (worker fetch raz/30s).

Companion docs

docs/BRAND.md — visual identity, color palette, helper components.
docs/FLOWS.md — szczegółowa mapa button → action.
docs/ARCHITECTURE.md — module structure, data flow.
CLAUDE.md — Claude Code rules (CORE GOAL, banned words, dual deploy).