Inspiration I'm a final-year physiotherapy student, and I kept seeing the same gap play out in clinic after clinic: a physiotherapist gives a patient a home exercise program, sends them off with a printed sheet or a verbal explanation, and then loses all visibility into what actually happens between appointments. Did they do the exercises? Did their pain change? Did they quietly stop halfway through because nobody was checking in?

That gap is where recovery falls apart. Patients forget the details, lose the sheet, or just don't know whether what they're feeling is normal. I wanted to build something that lived in that space: a companion that stays with a patient between sessions, without ever pretending to replace the physiotherapist who's actually treating them.

I'd also been building my frontend development skills alongside my clinical training, and this felt like the right project to bring both sides together: real clinical judgment about what a rehab routine should actually contain, paired with a real, working product.

What it does PhysioPal AI is a home exercise companion for physiotherapy patients. A patient searches or taps a body map to find their condition, gets a clinically written, multi-day exercise program with real video demonstrations, and works through it day by day: checking off exercises, logging pain, tracking weight and vitals, and leaving notes on how each exercise felt.

Along the way, the app surfaces two AI-powered features, both built with a specific safety principle in mind: the AI is allowed to help with logistics and phrasing, never with clinical judgment.

A rule-based tip engine watches a patient's recent pain trend and adherence, and only when a clear pattern fires does it suggest reducing intensity or progressing. The trigger logic is fixed, deterministic code; an LLM only rephrases the pre-approved message in a warmer tone, so it can never invent new medical advice. A scoped AI chat assistant answers questions grounded entirely in the patient's own logged data ("what's next," "how's my streak") and explicitly declines to assess personal symptoms, sharing general physiotherapy knowledge where relevant, but always redirecting anything about the patient's own case back to their physiotherapist.

Beyond that, the app includes a shareable PDF progress report a patient can hand to their real physiotherapist, a voice-guided workout mode using the browser's built-in speech API, and works as an installable PWA.

How I built it The stack: Next.js (App Router) and TypeScript on the frontend, Supabase (Postgres, Auth, and Row Level Security) for the backend, and Google Gemini for the two AI-assisted features. Styling is Tailwind CSS v4 with a custom design system, Recharts for the progress charts, and lucide-react for iconography. It's deployed on Vercel.

I started by scoping a deliberately small MVP, one condition, one routine, and basic logging, and then building outward sprint by sprint: authentication, condition content, daily logging, a multi-day program tracker, dashboard analytics, and finally the AI layer. Every clinical exercise routine in the seed data is one I wrote myself, using real dosages and progressions rather than placeholder content, since getting that right is the whole point of the app.

Challenges I ran into A few ones, in no particular order:

Deciding what the AI was not allowed to do. The easy version of this app has a chatbot that answers "Is my pain normal?" directly. I kept pulling that feature back, first to a fixed set of rule-based tips, then, when I needed a genuine chat feature, to one that's grounded only in the patient's own data and explicitly refuses to interpret symptoms. Getting the system prompt to hold that line consistently (general education yes, personal diagnosis no) took real iteration. A first-message ordering bug. My chat UI showed a hardcoded greeting bubble before any real conversation started, and I was sending that greeting to the Gemini API as the first message in the array, but the API requires the first message to come from the user, so every request was silently failing into a fallback response. Tracing that down meant adding real error logging instead of trusting a generic-sounding fallback message. A truncated-response bug from model "thinking." Newer Gemini models spend part of their output token budget on internal reasoning before writing the visible reply, so a modest maxOutputTokens was cutting real answers off mid-sentence. Fixing it meant explicitly disabling the thinking budget and raising the token ceiling. Keeping costs at zero before the hackathon. I originally built the AI features against the Claude API, then migrated both the tip-phrasing and the chat assistant over to Gemini's free tier, which was a genuinely different request/response shape, to make sure the app was fully runnable without anyone needing to pay for API access. Matching a reference design exactly several times. I went through a few real design pivots and had to keep the whole component library consistent through each change.

Accomplishments that I'm proud of Every clinical routine in the app is real, not placeholder content, but informed directly by my physiotherapy training. And the AI story isn't just "we added a chatbot"—it"'s a considered set of decisions about where automation is appropriate (adherence math, rephrasing, logistics) and where it explicitly isn't (interpreting an individual patient's pain).

What I learned Restraint is a feature. The most defensible part of this project isn't a feature I built; it's a feature I deliberately didn't build the obvious way. Turning down an easy, flashy AI chatbot in favor of a narrower, safer one was a real product decision, not a limitation, and it's the part of the build I'd most want a judge, or a future employer, to ask me about.

What's next for PhysioPal AI Real exercise-by-exercise progression across a program (rather than one repeated routine), a therapist-facing view so a clinician can actually assign and monitor a patient's plan, and persisted chat history are the next things on the list.

Built With

Share this project:

Updates

Submission history