AI-assisted patient intake app with voice capture, structured extraction, and offline persistence.
- 🎙️ Voice-to-text via browser Web Speech API (no paid STT needed)
- 🤖 AI data extraction using OpenRouter's Xiaomi MiMo-V2-Flash model
- 💾 Offline persistence - Patient records saved to browser
localStorage - 🔐 Google sign-in via Firebase Authentication
- 🔍 Search & Filter - Filter patients by name, symptoms, or date (dd/mm/yy)
- 🧪 Dev Mode - Generate random test patients with AI extraction (hidden in production)
- ⚡ Modern Stack - Vite + React + TypeScript + Tailwind + shadcn/ui
We chose Xiaomi MiMo-V2-Flash as our AI extraction model for several compelling reasons:
- Architecture: Mixture-of-Experts (MoE) with 309B total parameters, 15B active
- Context Window: 262,144 tokens (256K)
- Cost: FREE via OpenRouter ($0/M input & output tokens)
- 🏆 #1 Open-Source Model on SWE-bench Verified and SWE-bench Multilingual
- 📊 Comparable to Claude Sonnet 4.5 at only ~3.5% of the cost
- ⚡ High Throughput: ~69 tokens/second average
- 🟢 100% Uptime on OpenRouter
- Excels at reasoning and structured extraction - perfect for parsing clinical notes
- Supports hybrid-thinking mode for complex medical inference
- Open-source with transparent model weights
- Zero cost makes it ideal for prototyping and small clinics
We evaluated several models before settling on MiMo-V2-Flash:
- Groq llama-3.3-70b-versatile - Required paid API key
- Google Gemini - API quota issues
- NVIDIA Nemotron 3 Nano 30B - Did not follow JSON output instructions
- DeepSeek R1 - Also failed to return structured JSON
MiMo-V2-Flash provides the best balance of cost (free), capability (structured JSON extraction), and reliability.
We migrated from Netlify to Vercel for the following reasons:
- Better SPA Routing - Vercel handles client-side routing natively with
vercel.json - Faster Builds - Vercel's build times are noticeably faster for Vite projects
- Better DX - Automatic preview deployments and instant rollbacks
- Edge Functions - Better support for serverless functions if needed later
The project includes a vercel.json file that handles SPA routing:
{
"rewrites": [
{ "source": "/(.*)", "destination": "/" }
]
}This ensures that refreshing on any route (e.g., /dashboard) doesn't result in a 404.
git clone https://github.com/vijayho1/MedHelp.git
cd MedHelp
npm install
cp .env.example .env # create this file using the template below
npm run devOpen http://localhost:5173 and sign in with Google, then add a patient (voice or typed). Data persists in your browser.
# OpenRouter API (FREE - for AI extraction)
VITE_OPENROUTER_API_KEY=your_openrouter_key
# Firebase Auth
VITE_FIREBASE_API_KEY=AIzaSyD-iw-DFQQBarKfVbc0j1FsVcX2JMj2qB8
VITE_FIREBASE_AUTH_DOMAIN=medhelp-af68a.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=medhelp-af68a
VITE_FIREBASE_APP_ID=1:999268392916:web:71289a0c5fb6725d1a8041
VITE_FIREBASE_STORAGE_BUCKET=medhelp-af68a.firebasestorage.app
VITE_FIREBASE_MESSAGING_SENDER_ID=999268392916- Go to OpenRouter.ai
- Sign up / Sign in
- Navigate to API Keys
- Create a new key and add it to your
.env
Note: MiMo-V2-Flash is completely free to use!
- Push your code to GitHub
- Import project in Vercel Dashboard
- Add environment variables in Project Settings → Environment Variables
- Deploy! Vercel auto-deploys on every push to main
Ensure your Vercel domain is whitelisted:
- Go to Firebase Console
- Navigate to Authentication → Settings → Authorized domains
- Add your
.vercel.appdomain
| Category | Technology |
|---|---|
| Framework | Vite + React 18 |
| Language | TypeScript |
| Styling | Tailwind CSS + shadcn/ui |
| AI | OpenRouter (MiMo-V2-Flash) |
| Auth | Firebase Authentication |
| Speech | Browser Web Speech API |
| Storage | localStorage |
| Hosting | Vercel |
src/
├── components/
│ ├── PatientForm.tsx # Main form with AI extraction
│ ├── PatientCard.tsx # Patient display card
│ ├── VoiceRecorderWebSpeech.tsx # Voice recording
│ └── ui/ # shadcn/ui components
├── contexts/
│ ├── AuthContext.tsx # Firebase auth state
│ └── PatientContext.tsx # Patient CRUD + random generation
├── pages/
│ ├── Dashboard.tsx # Main dashboard with filters
│ ├── Login.tsx # Google sign-in
│ └── Index.tsx # Landing page
└── types/
└── patient.ts # TypeScript interfaces
- Uses browser's native Web Speech API
- No external STT service needed
- Works offline (for transcription)
The AI extracts structured data from clinical notes:
- Age, History, Symptoms
- Tests, Allergies
- Possible Condition (AI-inferred diagnosis)
- Recommendations (follow-up suggestions)
Filter patients by creation date using dd/mm/yy or dd/mm/yyyy format.
In development (npm run dev), a "Generate Random Patients" button appears to create test data with AI extraction. This is hidden in production builds.
| Issue | Solution |
|---|---|
| AI errors | Verify VITE_OPENROUTER_API_KEY is set |
| Auth blocked | Add Vercel domain to Firebase authorized domains |
| 404 on refresh | Ensure vercel.json is in project root |
| Duplicate transcription | Fixed in latest update - pull latest changes |
| No patients after refresh | localStorage was cleared; data is per-device |
- Replace localStorage with cloud database (Supabase/Firestore)
- Add audit logs per user
- Role-based access for clinics
- Export patient data (PDF/CSV)
- Multi-language support for voice input
MIT
Built with ❤️ using React, TypeScript, and AI