MedisynX is a MERN healthcare SaaS app for doctors, patient management, appointments, billing, and Clinical AI insights. The AI system now uses OpenRouter as the single backend provider integration, with Gemini 3 Flash as the primary model and a resilient fallback chain.
- Frontend: https://medisyn-x.vercel.app
- Backend: Render Node.js API
- Database: MongoDB Atlas
- AI provider: OpenRouter Chat Completions API
Primary model:
google/gemini-3-flash-preview
UI label:
Gemini 3 Flash
OpenRouter endpoint:
https://openrouter.ai/api/v1/chat/completions
The backend sends OpenAI-compatible chat payloads directly with fetch:
{
"model": "google/gemini-3-flash-preview",
"messages": [{ "role": "user", "content": "..." }],
"stream": true,
"max_tokens": 700,
"temperature": 0.35
}Required headers:
Authorization: Bearer <OPENROUTER_API_KEY>Content-Type: application/json
Optional attribution headers:
HTTP-Referer: <frontend app URL>X-Title: <app name>
API keys are read only from server environment variables and are never exposed to the React frontend.
MedisynX tries each model once, in order. The same conversation context is reused for every retry. Invalid or unauthorized API key errors stop the chain immediately.
Primary:
google/gemini-3-flash-preview
Fallbacks:
google/gemini-3.1-flash-lite-previewgoogle/gemini-3.1-flash-litegoogle/gemini-2.5-flash-litedeepseek/deepseek-chat-v3-0324:freemeta-llama/llama-3.3-70b-instruct:freemistralai/mistral-small-24b-instruct-2501:freemistralai/mistral-small-3.2-24b-instruct
The frontend receives metadata for the provider, model, label, fallback activation state, and attempted models. If all OpenRouter models fail, the UI stays stable and shows a local safety fallback with a user-friendly message.
The backend handles and normalizes:
- Missing
OPENROUTER_API_KEY - Invalid API key or unauthorized responses,
401and403 - Rate limits,
429 - Model unavailable,
404 - Provider or upstream outage,
5xx - Request timeout
- Network failure
- Empty responses
- Malformed JSON
- Malformed streaming chunks
Streaming is enabled by default. The server parses OpenRouter SSE chunks, reads data: lines, stops at data: [DONE], aggregates choices[0].delta.content, and safely handles chunk-level errors.
Create server/.env:
MONGODB_URI=your_mongodb_uri
JWT_SECRET=your_jwt_secret
JWT_EXPIRE=1d
JWT_REFRESH_SECRET=your_refresh_secret
JWT_REFRESH_EXPIRE=7d
OPENROUTER_API_KEY=sk-or-v1-your_key
OPENROUTER_MODEL=google/gemini-3-flash-preview
OPENROUTER_FALLBACK_MODELS=google/gemini-3.1-flash-lite-preview,google/gemini-3.1-flash-lite,google/gemini-2.5-flash-lite,deepseek/deepseek-chat-v3-0324:free,meta-llama/llama-3.3-70b-instruct:free,mistralai/mistral-small-24b-instruct-2501:free,mistralai/mistral-small-3.2-24b-instruct
OPENROUTER_HTTP_REFERER=http://localhost:5173
OPENROUTER_APP_TITLE=MedisynX
AI_STREAMING=true
AI_REQUEST_TIMEOUT_MS=20000
AI_MAX_TOKENS=700
AI_TEMPERATURE=0.35
PORT=5000
CLIENT_URL=http://localhost:5173Create client/.env:
VITE_API_URL=http://localhost:5000/api/v1Examples are also provided in server/.env.example and client/.env.example.
Prerequisites:
- Node.js 18+
- MongoDB Atlas database
- OpenRouter API key
Install and run the server:
cd server
npm install
npm run devInstall and run the client:
cd client
npm install
npm run devOpen http://localhost:5173, create a doctor account, then use Clinical AI.
Run backend provider tests:
cd server
npm testRun the production frontend build:
cd client
npm run buildThe OpenRouter provider tests mock:
- Normal Gemini 3 Flash response
- First-model failure with fallback activation
- Invalid API key stopping after one attempt
- Streaming SSE aggregation
- Empty response handling
AI is not configured yet
Check OPENROUTER_API_KEY in server/.env, then restart the server.
AI provider authentication failed
The key is missing, expired, malformed, or unauthorized. Create a new OpenRouter key and update OPENROUTER_API_KEY.
The AI provider is rate limiting requests
Wait briefly, reduce request volume, or add OpenRouter credits. The fallback chain will continue unless the error is an auth failure.
The selected AI model is temporarily unavailable
OpenRouter returned 404 or no provider for a model. The backend automatically tries the next configured model.
The AI request timed out
Increase AI_REQUEST_TIMEOUT_MS or retry. The default is 20000.
No streaming content appears
Set AI_STREAMING=false to use non-streaming JSON responses while debugging provider stream issues.
Frontend cannot reach backend
Confirm client/.env has VITE_API_URL=http://localhost:5000/api/v1 and the backend CORS CLIENT_URL matches the frontend URL.
MedisynX/
client/
src/
api/ # frontend API helper
components/ # navigation and shared UI
pages/ # dashboard, patients, Clinical AI, billing
utils/ # auth helpers
server/
ai-service/
openRouterProvider.js # OpenRouter endpoint, streaming, fallback chain
diagnosisService.js # clinical prompt, cache, local safety fallback
config/ # database config
controllers/ # route controllers
middleware/ # auth and error handling
models/ # Mongoose schemas
routes/ # Express routes
server.js # API entrypoint
- Clinical AI insights with Gemini 3 Flash and OpenRouter fallback support
- Confidence scoring and structured Markdown reports
- Doctor authentication with JWT and bcrypt
- Patient CRUD, appointments, billing, PDF reports
- PWA-ready React frontend with responsive UI
- MongoDB Atlas persistence
- Server-side API key handling only
ISC License