Inspiration
Rwanda has made remarkable progress in public health yet a painful gap remains: young people aged 15–35 consistently avoid seeking care for sensitive issues like HIV/STI testing, mental health support, family planning, and menstrual health. Not because services don't exist, but because seeking them feels unsafe. A young person in Kigali can order food anonymously in seconds. Yet booking a confidential health consultation means creating an account, revealing their identity, and navigating a system never built with their privacy in mind. For young women dealing with menstrual disorders, irregular cycles, or period-related pain, that barrier is even higher these topics carry deep stigma and are rarely discussed openly. What if getting health care felt as simple and private as sending a message? That question became Huzacare Hub.
What it does
HuzaCare Hub is a privacy-first health platform for young people in Rwanda. Its core promise access care without ever creating an account.
HuzaCare Hub gives every young person in Rwanda a private path to care with no account, no name, and no judgment. You can start by chatting with Claude in English, French, or Kinyarwanda, where it listens to your health concerns and walks you into a booking when you feel ready. Booking takes under 60 seconds: you enter only a phone number, pick a service and time slot, and receive an anonymous booking ID like GC-001. Your doctor then calls you at your chosen time seeing only that ID, never your name, and nothing is stored beyond the minimum needed to connect you with care.
Anonymous booking : clients book appointments using only a phone number and basic info. No login, no account, no trace. A unique booking ID (e.g. GC-001) is returned to track appointment status. Health chatbot : a keyword-aware assistant answers questions about HIV, STIs, mental health, family planning, menstrual health, and more. Sessions are tied only to a UUID token stored on the client no identity is ever persisted server-side. Doctor portal : doctors manage availability, view their daily schedule with open time slots, and track patient feedback. Admin dashboard : admins manage doctors, services, and articles, and monitor platform usage through live statistics. Health articles: public educational content accessible to anyone, no account required. Topics include menstrual health, reproductive care, and mental wellness.
How we built it
We built HuzaCare Hub as a full-stack, production-ready system in under 48 hours.
On the backend, we used Node.js with TypeScript, Express 5, and PostgreSQL on Neon, with Prisma ORM for type-safe data modeling. We implemented JWT-based role authentication for doctors and admins, with validation using Zod, and secured the API using Helmet, CORS, and rate limiting.
On the frontend, we designed a mobile-first interface focused on speed and simplicity, allowing users to chat, read health content, and book appointments in under a minute with no account required.
At the core of the experience is Claude AI, which powers the chatbot. It provides culturally aware, multilingual guidance and helps users move from asking questions to booking care while maintaining full anonymity.
The entire system is documented with OpenAPI and deployed on Render.
Challenges we ran into
Anonymous identity without chaos. How do you maintain a session for someone with no account? We solved it with a client-generated UUID sessionToken for the chatbot issued on the first message, stored only in the frontend, never tied to any personal data. PostgreSQL type mismatch on foreign keys. Our Booking.id is a plain TEXT field (GC-001), but Feedback.bookingId was initially annotated @db.Uuid. PostgreSQL refused to create the foreign key constraint between a uuid column and a text colum caught only at prisma db push time. Fix: remove the @db.Uuid annotation. Render deployment wrong entry point. Render defaulted to node index.js instead of node dist/server.js, and the build command was only npm install with no TypeScript compilation. Fix: add a render.yaml and update the build script to prisma generate && tsc.
How Claude AI powers
Claude is not a feature. It is the front door to the entire platform. When a young person is too anxious to book an appointment directly, they start a conversation with the chatbot first. Claude (claude-haiku-4-5-20251001) is the engine behind that experience, integrated with three intentional design choices. Culturally sensitive system prompt. Claude is given a carefully crafted context that makes it aware of Rwandan youth culture. It responds in English, French, or Kinyarwanda and never asks for identifying information. Anonymous conversation memory. The last 5 exchanges per session are fetched from the database and passed as message history, giving Claude full context without storing any identity. Guided escalation. Claude knows the 4 available services and gently encourages users to book an anonymous consultation when a question requires professional care.
Accomplishments that we're proud of
Zero-auth client flow: a young person can book a health appointment in under 60 seconds with no account 24 documented API endpoints with a full OpenAPI 3.0 spec, live at /api/docs Role-based JWT with strict middleware separation no admin token can access doctor routes and vice versa Slot conflict detection double-booking the same doctor at the same time is impossible at the database level Auto-recalculated ratings every feedback submission recomputes the doctor's average rating in real time TypeScript strict mode with 0 errors across the entire codebase
What we learned
Privacy is a feature, not a setting. Designing for anonymity from the start forces every schema decision to be intentional you can't retrofit privacy after the fact. This rang especially true for menstrual and reproductive health: the moment a platform requires a name or login, young women disengage. Prisma is powerful but opinionated. Multi-file schemas, @db.Uuid vs plain String, and the difference between prisma generate and prisma db push all have real consequences at deploy time. ts-node and tsc are not the same compiler. Understanding how ts-node resolves types at runtime versus how tsc resolves them statically saved us from a subtle but critical production bug. Rate limiting is empathy. Protecting /api/chat isn't just about abuse prevention it's about ensuring the chatbot stays available for every young person who needs it.
What's next for Huzacare
Mobile-first frontend: a React Native app so the full experience works on low-end Android devices common among Rwandan youth LLM-powered chatbot: replace the keyword matcher with a model fine-tuned on Rwandan health guidelines (RSSB, RBC protocols), with dedicated flows for menstrual health tracking and cycle-related questions Menstrual health tracker: an anonymous, in-app cycle tracker so young women can log symptoms and share relevant history with their doctor before a consultation no account needed SMS notifications: booking confirmations and reminders via Africa's Talking API, reaching users without smartphones or data Analytics dashboard: heatmaps of booking demand by service and time slot to help clinics optimise scheduling Multi-language: support full Kinyarwanda and French localisation for both API responses and the chatbot Optional client accounts for users who want to track their history, while keeping anonymous access as the default
Built With
- axios
- bcryptjs
- claude
- cors
- dotenv
- eslint
- express-rate-limit
- express.js
- github
- helmet
- javascript
- jwt
- morgan
- neon
- node.js
- nodemon
- openapi
- postgresql
- prettier
- prisma
- react
- react-hook-form
- react-router
- render
- swagger-ui
- tailwind-css
- tanstack-query
- ts-node
- typescript
- vite
- zod
Log in or sign up for Devpost to join the conversation.