A bilingual care system for one Mexican-American family.
My mom was carrying the entire memory of three elders' care alone. I wanted to build her a tool that absorbed the cognitive load, without making her family install an app, learn a UI, or speak English. This is what I built. Eleven days from empty repo to a private SMS + web system the whole family will use, including the grandparents who only speak Spanish. The first family text is queued for the day Twilio approves outbound carrier delivery.
The problem
Three elders need ongoing care: my dad (Pa), my mom-in-law (Ma), and an uncle (Ricky). Six to seven adult family members spread across two cities help out. Coordination happens in three places at once: group text, phone calls, and my mom's head.
The pattern was always the same:
- Mom takes Pa to cardiology. The doctor changes a medication. Mom remembers.
- Aunt Rosa picks up Pa for a follow-up two weeks later. Doesn't know about the medication change. Asks Mom over text.
- Mom has been in three other appointments since. Has to dig back through her memory.
- Multiply by three elders, multiply by two years.
Then the household coordination layered on top: potlucks where Mom and Aunt Rosa both bring tamales, landscape days where four people sign up and three back out the morning of, cleaning rotations where Tía Carmen drives 90 minutes assuming the cleaning is on when the date had quietly moved.
The thing every elderly-care family knows: the institutional memory shouldn't live in one person's brain. But every off-the-shelf tool either (a) requires the elders to use a smartphone app or (b) requires English fluency.
The design constraints
Before writing a line of code I locked four constraints with the family:
- SMS is the universal interface. Pa and Ma have flip phones. Aunt Rosa has an iPhone. My uncle Tomás won't install an app. SMS works for everyone. A US local number means no carrier confusion.
- Spanish-first for elders. Ma reads Spanish. Pa reads basic Spanish. Anything they receive (confirmations, weekly digests, reminders) has to be Mexican Spanish, register appropriate for elders ("usted," not "tú"), with medical jargon translated to plain language ("presión," not "hipertensión arterial").
- One person to set up. A few minutes per family member to onboard. Each new member should be onboarded by the coordinator in under 60 seconds, no email sent, no password required. They start texting immediately.
- Private. Always private. No advertising network, no third-party analytics, no data resale. Family medical context never leaves the family.
The stack
How it works
Texting a care update
A family member sends an SMS to (989) 762-4030:
"Took Pa to cardiology today. Dr. Martinez said BP is stable, continue current meds, follow up in 6 months."
The webhook lands at a Supabase Edge Function which:
- Validates the Twilio signature against a canonical URL (Supabase rewrites
req.urlinternally; that took a day to find). - Looks up the sender's number in
contributor_phonesto get their family member record + preferred language. - Calls Claude with the message + a curated
<care_context>block (current meds, recent appointments, recent notes, upcoming events). - Claude classifies intent (query, care write, event commitment, or house photo) and emits structured JSON.
- The function inserts the appropriate rows and replies with a confirmation in the sender's language.
Asking a question
Same number, different intent:
"What medications is Pa taking right now?"
The function pulls Pa's active medications, hands them to Claude as context, and Claude composes a 320-char SMS-friendly answer. If the sender's preferred language is Spanish, the answer comes back in Mexican Spanish, with medication names preserved as-is and frequency ("once daily") translated to "una vez al día."
The bilingual moment that mattered
Records are saved in the contributor's original language to preserve their phrasing. Translation happens at view time. The use case I optimized for: a grandchild with weak Spanish reading the Spanish view aloud to Ma. Every Spanish translation has to be something they can read confidently. That requirement quietly drove a lot of the prompt work.
Architectural decision that mattered: care context goes in the user message, not the system prompt. A coordinator's note containing "ignore previous instructions" can't hijack the model that way. Stored prompt injection is the SMS equivalent of XSS. We caught it in /cso review before launch.
Household logistics + photos
The medical features were the seed. Then came events (landscape days, cleaning rotations, potlucks with dish-duplicate detection), a /house photo board (text any casual photo to the line; Claude classifies it as casual vs. medical and routes accordingly), a bilingual /calendar page merging events + appointments + refills + follow-ups, and an SMS broadcast layer that pings the family the moment any new event or appointment lands.
By v1.0 the system runs three different Sunday-and-daily SMS digests (weekly recap, daily morning huddle, event reminders), grouped by each member's preferred language. Everything Ma sees is Mexican Spanish. Everything Mom sees is English. Same database.
What the architecture looks like
- 10 Postgres tables.
families,family_members,contributor_phones, 5care_*tables,events,event_commitments,house_photos. - Row-level security on every table. Family isolation via two SECURITY DEFINER helpers (
get_user_family_id,get_user_family_role). Anon JWT + user JWT for the API; service-role only inside admin actions after a role check. - 5 Edge Functions.
family-care-mcp(web API + admin),sms-ingest(Twilio webhook + Claude classifier with 4 intents),voice-ingest(transcribed voicemails forwarded with a shared secret),weekly-digest+daily-digest+event-reminders(3 crons via pg_cron, vault-stored secret). - Soft-delete throughout. Every care/event row has
archived_at;active_*views withsecurity_invoker = truefilter. A leaked service-role key can't bypass family scoping. - Translation at view time. Records stored in original language; Claude translates on read for Spanish viewers, preserving proper nouns and converting medical jargon to plain Mexican Spanish.
The build, day by day
/plan-eng-review which caught 6 issues including the silent LIMIT 1 bug if a user joined two families./cso caught 5 issues: stored prompt injection in care context, XSS in the web view, missing CRON_SECRET on weekly-digest, x-internal-forward bypass on voice-ingest, missing .gitignore. All fixed before launch.What's built
What success looks like
The system is built. What I'm watching for once Twilio A2P approves outbound delivery and the family rolls in:
- Adoption: 5+ of 7 family members texting at least once in the first 30 days. Below 5 and the network effect doesn't activate.
- Mom relief: qualitative. "I don't feel like I'm holding it all in my head anymore." The whole point.
- Bilingual reading: Ma or Pa being read a Spanish weekly digest aloud, and them understanding it without clarification.
- Coordination wins: at least one potluck where the duplicate-dish detection prevents the tamales clash. At least one landscape day where the helper-nudge fills the open slots.
↻ I'll add a "30 days in" section to this page once the first run completes.
What I'd do differently
- Build the bilingual layer earlier. Retrofitting Spanish on day 6 was twice the work of building it in from day 1. Mexican Spanish register, "usted" for elders, medical jargon translation. These are design constraints, not localization tasks.
- Run /cso before, not after. Stored prompt injection is now top-of-mind for me; I would've caught it sooner if I'd run a security review on the second day instead of the eighth.
- Soft-delete from the first migration. Adding
archived_atretroactively is fine, but I had to update queries everywhere. Patterns are cheaper to set up early. - Check Vercel git integration after every project rename. Spent 30 minutes debugging a "site not updating" issue that was just a disconnected GitHub link.
What unlocked the speed
- Claude Code's plan/review skills.
/plan-eng-reviewon day 1 caught architectural issues that would've taken me a week to find through trial-and-error./csoran security review faster and more thoroughly than I could. - Supabase as the spine. Postgres + RLS + Edge Functions + Storage + Auth in one project meant I never had to integrate two services. Family isolation comes "free" once
get_user_family_id()is the only knob. - Boring stack on purpose. Static HTML, no build step, no framework. The web app is one HTML file per language. Vercel deploys on push. Updating a page means editing the HTML. No compile step in the way.
- Twilio's reliability. A2P 10DLC registration is the slowest moving part; everything else just works.
Bilingual systemsFamily opsSMS UXClaude APISupabase RLSTwilio A2PAI-assisted dev