# TEPY

> AI physiotherapy for muscle pain: record where it hurts, get a plan of self-massage and exercises, follow it on video.

Case study by Paolo Gianfelici (Full-stack developer & UI/UX designer). https://paologianfelici.com/work/tepy

- **Role:** Fullstack developer: the whole mobile app and its Cloud Functions
- **Client:** TEPY
- **Period:** 2023 – today
- **Platforms:** iOS and Android from one Flutter codebase
- **Stack:** Flutter, Dart, Riverpod, go_router, Firebase Auth, Firestore, Cloud Functions, In-app subscriptions, Video player, Patrol
- **App Store:** https://apps.apple.com/it/app/tepy-ai-for-muscle-pain/id6449585005
- **Google Play:** https://play.google.com/store/apps/details?id=com.tepy.app

TEPY turns the first visit to a physiotherapist into a conversation with the phone. You show it where it hurts on a 3D body, how much, since when, what it feels like and which movements set it off; it answers with a plan of self-massage and exercise sessions spread over the following weeks.

Every session is a playlist of short videos with a timer, sets and repetitions and spoken cues. Around the plan sit routines for the day (warm-up, cool-down, mobility, muscle recovery, a pause at the desk) and a progress screen that keeps count.

*TEPY is on the App Store and Google Play. The recordings on this page do not touch it: they run the current source code as a self-contained build with in-memory accounts and database and a stand-in for the back end. The exercises, their videos and the pictures are the app’s own, bundled with the build; the user, the profile, the pain points and the progress are invented, and nothing was sent anywhere.*

- 95%: of the app’s commits are mine (547 of 574)
- 65k: lines of Dart, excluding generated code
- 7: languages in the interface
- 3 yrs: of continuous development, since May 2023

## From “it hurts here” to a plan you follow

### An onboarding that sets up the plan

Apple or Google sign-in, or a company code for employees of partner companies. Consent comes with a plain explanation of what the algorithm does and does not do. Then a short profile (age, body, the kind of work day, how active you are, sports and the tools you own), which the back end uses to pick exercises.

### Pain, located on a 3D body

The body can be rotated and zoomed until the tap lands on the exact spot, which the back end resolves to a zone. Intensity on a 0–10 scale with a description for every level, how long it has lasted, the sensations around it, and which movements hurt and at what point, each test shown as a looping video.

### A plan that follows the pain

The highest pain level decides the length of the plan, from three to about seven weeks, and which days are self-massage, exercises or rest. When the pain points change, the plan asks to be recalculated; the week strip shows what is due and what is done.

### Sessions as full-screen video

A session is a playlist. Each exercise plays full screen with a timer or a repetition count, the details a swipe away and spoken cues; the next one is a swipe up. Leaving halfway keeps the progress for later.

### Routines for the rest of the day

Warm-up, cool-down, mobility and muscle recovery are built on request from the body areas to work on and the tools at hand. The wellbeing area adds short routines for the morning, the desk and the evening.

### Progress and subscription

Streak, time spent, exercises done and a wellbeing score keep the plan honest. Full access is a subscription through the App Store or Google Play, verified on the server before anything unlocks.

## How it was built

### State and navigation

Riverpod throughout, with generated providers and immutable models (freezed, json_serializable). One go_router redirect decides every entry point (sign-in, consent, profile completion, forced update), so a deep link or a restart always lands where the account actually is.

### Firebase, and the functions behind it

Auth for Apple, Google and email-link sign-in; Firestore for the user’s plan, sessions and progress; Crashlytics and Analytics. The Cloud Functions I wrote alongside the app verify App Store and Google Play subscriptions on the server, synthesise the spoken cues and send the scheduled reminders. The clinical logic (assessments, programmes, exercise selection) lives in a REST API built by the back-end team.

### Keeping a health app shippable

Integration tests with Patrol on the iOS simulator and on a 16 KB-page Android emulator, the configuration Google Play now requires. A compliance pass for the EU AI Act and medical-device rules: disclosure labels, consent wording, and nothing that reads as a diagnosis.

## Recording a live app: The app is real. Everything it shows is not.

TEPY has real users, real health data and a paid subscription behind it. None of that belongs in a portfolio, so the recordings use a copy of the current code that runs on its own.

- **The current code, built for the browser.** A Flutter web build at phone size, told it runs on an iPhone. What only exists on a phone (the App Store, push notifications, the tracking prompt, crash reporting) is replaced by small stand-ins.
- **Firebase without Firebase.** Sign-in and the database run on the in-memory fakes the project already uses in its tests; one of them needed a two-line patch to work in a release build. A switch in the address loads either a first launch or a returning user with a few weeks of history.
- **A stand-in for the REST API.** The HTTP client is swapped for one that answers inside the app, with the routes and JSON shapes the models expect: pain zones, movement tests, plans, routines and twenty of the service’s exercises, with the names and key points its catalogue gives them.
- **The app’s own media, recorded offline.** The pictures and the sign-in video are the ones bundled with the app. The exercise, movement-test and self-massage videos, their thumbnails and the icons come from the CDN the app streams them from: fetched once by a script, scaled down and bundled with the demo. The recorder refuses any request that leaves the machine, so a take cannot reach the real service.

The logo, the interface, the 3D body model, the pictures, the exercises and their videos are the app’s own. The user, the pain points, the plans and the progress are sample content made for this portfolio.

## Recordings

- **From a pain point to a plan** (83 s): Where it hurts on a 3D body, how much, since when, what it feels like and which movements trigger it, then the plan is recalculated and today’s self-massage session starts. https://paologianfelici.com/media/tepy/clips/pain-point.mp4?v=96053f2e2f
- **Sign-up and onboarding** (91 s): Social sign-in, consent, a short profile (body, work day, activity, sports), then the subscription offer and a guided tour of the home. https://paologianfelici.com/media/tepy/clips/onboarding.mp4?v=af2813d1e7
- **Routines and progress** (64 s): Fitness routines built from the areas to work on and the tools at hand, the full-screen player, quick routines for the day, and the progress screen. https://paologianfelici.com/media/tepy/clips/routines.mp4?v=09675d1e22
