CareTie

a care app for elderly heart failure patients and the people who look after them

timeline
apr to may 2026
role
ui/ux design + full stack
team
7 people
skills
ui/ux · react native · supabase · ai integration

Overview

Seven of us built a heart failure care app in six weeks. I designed and shipped two surfaces of it: the AI assistant patients talk to, and every screen where they prove who they are.

Design

  • Designed the assistant's conversation UI, safety disclaimer, and three distinct waiting states
  • Built the shared style system the six auth screens run on
  • [The accessibility decision that mattered most: type size, tap targets, or contrast]

Engineering

  • Wired the assistant to a hosted LLM with a care-specific system prompt
  • Added voice input: record, transcribe with Whisper, drop the text in the box
  • Wrote phone validation from scratch, US and international

Scope

  • 19 of the team's 96 commits, across 6 weeks
  • Two features owned solo: the assistant, and account recovery
  • [Research contribution, if the notes support it]
photo soon
photo soon
photo soon
photo soon
photo soon
photo soon

Problem

Heart failure is managed at home, by people the interface was not designed for

A heart failure patient tracks medications, watches for symptoms that mean "call someone now" versus "mention it next visit," and does this daily, often past 70, often with a caregiver half a state away. The apps that serve them tend to assume a younger, faster, more confident user.

[Grace's notes: the patient's situation, the caregiver's, and the number that grounds it. If there was a startup partner brief, the constraint they handed the team goes here.]

How might we let a patient ask a question about their own care without needing to know the right words for it?

Process

The assistant started as a chat box and stopped being one

The first version, in week one, was the obvious thing: a text input, a send button, a list of bubbles. It worked and it was wrong for the user. Typing a symptom question on a phone keyboard is exactly the task an elderly patient with unsteady hands is least equipped for, and the blank input gave no hint about what the assistant was even for.

[Grace's notes: what testing or feedback made this concrete, if any.]

media soon

Three problems, solved in the order they blocked people

Saying it out loud. I added a mic button that records, sends the audio to Whisper for transcription, and puts the text in the input box rather than sending it. That last choice matters: transcription gets names of medications wrong, and the patient gets to see and fix it before it goes anywhere.

Knowing what it is. A disclaimer appears before the first message and stays reachable from a help icon in the header. It says plainly that Kozy is not a doctor, and it names the escalation path (call your care team, call 911). The assistant's system prompt carries the same rule, so the tone holds even when the model is improvising.

Knowing it heard you. Voice adds two new kinds of waiting that a typing indicator cannot cover. I gave each its own state and label: "Listening, tap mic to stop," "Transcribing," and "Kozy is typing." The mic and send buttons disable against each other so the three states can never overlap (there is no legal way to be recording and sending at once).

What shipped

Kozy, a care assistant with a mouth and a conscience

media soon

Responses render as markdown, so the model's lists and bold actually land as lists and bold instead of asterisks (small thing, large readability difference on a small screen). Failures return a written apology in the chat rather than an error toast, because an elderly user reading "API error 502" learns nothing they can act on.

The account surface, which is where trust gets lost

I owned password reset, forgot password, phone verification, email changing, onboarding, and profile editing. This is unglamorous work that decides whether someone gets into the app at all.

media soon

The piece I would show in an interview is the phone validation. Off the shelf validators either accept anything with ten digits or drag in a large internationalization dependency. I wrote one that knows US rules (area codes cannot start with 0 or 1), recognizes 50+ country codes with their real maximum local lengths, rejects the obvious fakes (5555555555, 1234567890), and formats as you type. Every failure returns a specific sentence, so the user is told what is wrong instead of that something is.

A style system the auth screens share

Six screens needed to look like one product while five other people worked in the same repo. I pulled the auth palette, inputs, buttons, and the leaf motifs into a single shared module so screens compose from named pieces rather than re-declaring colors. It also meant my teammates could add an auth screen without asking me what the green was.

Outcomes

[n]

[the number: testers, pilot users, or what the startup validated]

50+

country codes handled by the validation, with real per-country lengths

[Grace's notes: what the startup shipped or validated, plus any testing results. If nothing was measured, say what you would measure: time to first successful question, share of assistant messages sent by voice, password reset completion rate.]

One thing I would do differently

The assistant sends each message without the conversation history, so Kozy cannot answer "what about the other one?" A patient asking a follow-up gets a confused answer, and follow-ups are how people actually talk. It was a two-line fix I did not prioritize because the feature demoed fine in single questions, which is a good lesson about demoing your own work: I kept testing it the way it worked instead of the way it would be used.

[Optional second reflection from Grace's notes.]