Medical Research Skills for Claude Code, Codex, Cursor & Copilot
58 项开源技能,覆盖完整的医学研究全生命周期。由医生构建,基于真实出版物测试。
AI 翻译
尚未收集仓库信息。
尚未检测到更新。GitHub 发布版本后会显示在这里。
制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Educación en salud pensada para personas mayores del Noroeste Argentino: letra grande, botones amplios, ingreso con el rostro en lugar de contraseñas, clases en video, calculadora de IMC y orientación por síntomas con machine learning.
[!IMPORTANT] La plataforma es orientativa y educativa. No da diagnósticos ni reemplaza la consulta con profesionales de la salud, y así lo dice en cada pantalla donde muestra resultados.
En Salta y el resto del NOA muchas personas mayores viven lejos de los centros de salud y tienen poca experiencia con la tecnología. Las aplicaciones de salud habituales les piden recordar contraseñas, leer letra pequeña y tocar botones diminutos. Salud Para Salta y NOA intenta sacar esas barreras del medio:
| Para quién | Qué encuentra |
|---|---|
| Personas mayores y sus familias | Clases en video sobre nutrición, ejercicio, salud cardiovascular, diabetes y salud mental; una calculadora de IMC que explica el resultado con recomendaciones; y una herramienta que orienta a partir de síntomas y siempre recomienda consultar a un médico. Para entrar solo necesitan su DNI/cédula y su rostro. |
| Docentes y profesionales de la salud | Un panel para publicar y administrar sus propias clases (video, PDF o artículo) y ver estadísticas por categoría. |
| Administración | Permisos para gestionar cualquier clase y a los usuarios a través de la API. |
El proyecto nació como Trabajo Final Integrador de la Licenciatura en Ciencia de Datos (UPATECO, 2025). El análisis académico completo, que trata la ética de datos, la accesibilidad y la estrategia de comunicación, está en TRABAJO_FINAL_INTEGRADOR_COMPLETO.md.
El diseño parte de la idea de que la persona usuaria puede ver poco, tener poca precisión con el dedo o no conocer las convenciones de la web. Esto es lo que hace el código (globals.css, components/ui, Navbar.tsx):
lang="es", los landmarks llevan nombre (role="navigation" con aria-label), el enlace activo usa aria-current y el menú móvil aria-expanded. Los campos informan sus errores con aria-invalid y aria-describedby, las alertas usan role="alert", los botones de carga aria-busy y los indicadores de espera aria-live.@vladmandic/face-api (TinyFaceDetector y 68 puntos faciales) mide si el rostro está centrado, si tiene buen tamaño, si la detección es confiable y si hay buena iluminación, y toma cada foto sola cuando la calidad es suficiente. La persona no tiene que apretar ningún botón.@simplewebauthn/server, y el frontend incluye el cliente en lib/webauthn.ts. La interfaz todavía no los ofrece (ver Estado del proyecto).Los permisos se aplican en el backend con los middlewares protect (JWT) y authorize(...roles). Así se reparten:
| Acción | usuario | docente | admin |
|---|---|---|---|
| Ver clases públicas, usar IMC y orientación por síntomas | ✅ | ✅ | ✅ |
| Editar el perfil, cambiar la contraseña y actualizar el rostro | ✅ | ✅ | ✅ |
| Crear clases y ver «Mis clases» y estadísticas | — | ✅ | ✅ |
| Editar o eliminar clases | — | solo las propias | todas |
Listar o eliminar usuarios (GET/DELETE /api/users) | — | — | ✅ |
El registro público solo crea cuentas de usuario o docente. Un rol de administrador se asigna desde el servidor con npx tsx src/scripts/updateUserRole.ts <email> admin.
seedClases.ts carga 15 clases de ejemplo en 7 categorías: nutrición, salud mental, ejercicio físico, salud cardiovascular, diabetes, salud ósea y prevención.Recibe el peso (kg) y la altura (cm). Calcula el índice en el servidor, lo clasifica (bajo peso < 18,5 ≤ normal < 25 ≤ sobrepeso < 30 ≤ obesidad) y devuelve recomendaciones para cada rango. Cada cálculo queda guardado en el historial de la persona, y la API devuelve los últimos 10.
saludsalta-disease-predictor. La carpeta disease-predictor de este repositorio es solo una referencia a ese repositorio.Estas capturas muestran solo páginas públicas. No se completó ningún formulario ni se inició sesión.
En el celular, de izquierda a derecha: portada, menú abierto con botones grandes e ingreso con reconocimiento facial.
Las pantallas que requieren sesión se capturaron corriendo el proyecto en local, con las clases de ejemplo de seedClases.ts y una cuenta docente de prueba. Así no aparecen datos de personas reales, y además la API del sitio publicado está fuera de línea hoy (ver Estado del proyecto). La orientación por síntomas usa el modelo real del servicio de predicción.
En el celular: clases, resultado del IMC y resultado de la orientación por síntomas.
flowchart LR
P["Persona usuaria<br/>navegador o celular"] --> F["Frontend<br/>Next.js 14 + Tailwind<br/>face-api en el navegador<br/>Vercel"]
F -->|"REST + JWT<br/>/api/auth, /api/clases,<br/>/api/health, /api/users"| B["Backend API<br/>Express + TypeScript<br/>Railway"]
B --> DB[("MongoDB Atlas<br/>usuarios, clases,<br/>historial de IMC")]
F -->|"GET /api/sintomas<br/>POST /api/predict"| D["Disease Predictor<br/>FastAPI + scikit-learn<br/>Railway, repositorio aparte"]
B -.->|"POST /predict<br/>alternativa por reglas"| M["ml-service<br/>FastAPI, en este repo"]
| Pieza | Carpeta | Qué hace |
|---|---|---|
| Frontend | frontend/ | Next.js 14 (App Router). Tiene 13 páginas: portada, sobre nosotros, privacidad, términos, registro, ingreso, panel, perfil, clases, IMC, orientación y las dos del panel docente. La sesión (usuario y JWT) se guarda con Zustand en localStorage, y Axios agrega el token a cada pedido. |
| Backend | backend/ | API REST en Express + TypeScript con Mongoose. Se ocupa de la autenticación (contraseña, rostro y WebAuthn), los roles, las clases, el IMC y los usuarios. También expone POST /api/health/predictor, que consulta al ml-service y, si este no responde, devuelve una recomendación genérica de consultar a un médico. |
| Disease Predictor | disease-predictor (repositorio aparte) | FastAPI que carga un modelo Random Forest (modelo_enfermedades.pkl) con 132 síntomas binarios. La página de orientación lo llama directamente con NEXT_PUBLIC_DISEASE_PREDICTOR_URL. |
| ml-service | ml-service/ | Predictor alternativo y más simple (base de conocimiento por reglas con 6 condiciones). Lo usa el endpoint /api/health/predictor del backend; la interfaz actual usa el Disease Predictor. |
Ingreso con el rostro, paso a paso:
sequenceDiagram
actor U as Persona
participant N as Navegador (face-api)
participant API as Backend
participant DB as MongoDB
U->>N: Escribe su cédula/DNI y pulsa "Verificar con mi rostro"
N->>N: Abre la cámara y detecta el rostro cada 0,5 s
N->>N: Captura automáticamente cuando la calidad es buena
N->>API: POST /api/auth/face-login (cédula + foto)
API->>DB: Busca la cuenta por cédula
Note over API: Si es docente, también valida la contraseña con bcrypt
API->>API: Compara la foto con las del registro
API-->>N: JWT (7 días por defecto) + datos básicos
N-->>U: Entra al panel
Esto es lo que hace el código:
select: false en el modelo, así que nunca se devuelven en las respuestas por defecto.JWT_SECRET, que vencen a los 7 días por defecto (JWT_EXPIRES_IN). El servidor no arranca si falta JWT_SECRET y no existe un valor por defecto.protect + authorize). Un docente solo puede editar o borrar sus propias clases, y nadie puede registrarse como administrador desde el formulario público.RATE_LIMIT_WINDOW_MS y RATE_LIMIT_MAX_REQUESTS), y 10 intentos fallidos cada 15 minutos en registro, ingreso con contraseña e ingreso facial.helmet y un CORS con lista de orígenes permitidos (el dominio publicado, localhost:3000 y FRONTEND_URL). El frontend envía X-Frame-Options: DENY, X-Content-Type-Options: nosniff y Referrer-Policy: strict-origin-when-cross-origin, y oculta X-Powered-By.JWT_SECRET y el resto de los secretos viven solo en las variables de entorno de Railway (backend) y Vercel (frontend). Los .env están en .gitignore, los .env.example solo contienen valores de ejemplo como <usuario>:<contraseña>@<cluster>, y railway-env-setup.sh toma los secretos de la terminal en lugar de tenerlos escritos.[!WARNING] La comparación facial y la verificación de WebAuthn en el servidor todavía son un prototipo. Por eso, en producción (
NODE_ENV=production) el ingreso facial y las rutas de WebAuthn responden 503 y solo se entra con contraseña. Para probarlos en desarrollo hay que definirALLOW_INSECURE_BIOMETRIC_LOGIN=true. Los detalles y el plan para resolverlo están en Estado del proyecto.
| Capa | Tecnologías |
|---|---|
| Frontend | Next.js 14.2 (App Router), React 18, TypeScript, Tailwind CSS 3, Zustand, Axios, @vladmandic/face-api, @simplewebauthn/browser |
| Backend | Node.js, Express 4, TypeScript 5, Mongoose 8, jsonwebtoken, bcryptjs, helmet, cors, express-rate-limit, @simplewebauthn/server, Axios |
| Machine learning | Python 3.11, FastAPI, scikit-learn 1.6 (Random Forest), pandas, joblib, Uvicorn |
| Datos | MongoDB Atlas (producción) y MongoDB 7 (local) |
| Infraestructura | Vercel (frontend), Railway (backend y predictor), dominio propio saludadultomayor.org |
Requisitos: Node.js 20 o superior (probado con 22), npm, Python 3.11 o superior y una instancia de MongoDB. El código usa mongodb://localhost:27017/fabi_bd si no se define MONGODB_URI.
git clone https://github.com/ronalc90/saludSalta_Noa.git
cd saludSalta_Noa
npm ci # instala frontend y backend (workspaces de npm)
Si no tienes MongoDB instalado, puedes levantar uno con Docker:
docker run -d --name salud-mongo -p 27017:27017 mongo:7.0
Crea backend/.env a partir de backend/.env.example. Variables que lee el código:
| Variable | Obligatoria | Para qué |
|---|---|---|
JWT_SECRET | ✅ | Firmar las sesiones. Usa una cadena larga y aleatoria, por ejemplo la salida de openssl rand -hex 32. |
MONGODB_URI | ✅ para los scripts | Conexión a MongoDB (en Atlas: mongodb+srv://<usuario>:<contraseña>@<cluster>/fabi_bd). El servidor usa la base local si falta, pero seedClases.ts la necesita. |
PORT | — | Puerto de la API (por defecto 3001). |
FRONTEND_URL | — | Origen extra permitido por CORS. |
JWT_EXPIRES_IN | — | Duración de la sesión (por defecto 7d). |
ML_SERVICE_URL | — | URL del ml-service (por defecto http://localhost:8001). |
WEBAUTHN_RP_NAME, WEBAUTHN_RP_ID, WEBAUTHN_ORIGIN | — | Configuración de WebAuthn (por defecto localhost). |
RATE_LIMIT_WINDOW_MS, RATE_LIMIT_MAX_REQUESTS | — | Límite global de solicitudes. |
cd backend
npx tsx src/scripts/seedClases.ts # opcional: carga las 15 clases de ejemplo
npm run dev # API en http://localhost:3001 (tsx en modo watch)
[!CAUTION]
seedClases.tsborra las clases existentes, y si no existe una cuenta de administrador de ejemplo, la crea con una contraseña fija escrita en el script. Úsalo solo en una base local, cambia esa contraseña y nunca lo corras contra producción. El scriptnpm run seedestá pensado para crear usuarios de demostración, pero hoy falla porque esos usuarios no tienen cédula (ver Estado del proyecto).
Para compilar como en producción: npm run build && npm start.
git clone https://github.com/ronalc90/saludsalta-disease-predictor.git
cd saludsalta-disease-predictor
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --port 8000
cd ml-service
pip install -r requirements.txt
python -m uvicorn app.main:app --reload --port 8001
Crea frontend/.env.local (tiene prioridad sobre el .env.production del repositorio) con:
| Variable | Para qué |
|---|---|
NEXT_PUBLIC_API_URL | URL del backend, por ejemplo http://localhost:3001. |
NEXT_PUBLIC_DISEASE_PREDICTOR_URL | URL del servicio de predicción, por ejemplo http://localhost:8000. |
cd frontend
npm run dev # http://localhost:3000
Para una build de producción: npm run build && npm start.
Así se despliega cada pieza, según DESPLIEGUE.md, backend/railway.json y la configuración de Vercel:
| Servicio | Plataforma | Configuración |
|---|---|---|
| Frontend | Vercel | Proyecto Next.js con Root Directory frontend, comando npm run build y dominio saludadultomayor.org. Variables: NEXT_PUBLIC_API_URL y NEXT_PUBLIC_DISEASE_PREDICTOR_URL. |
| Backend | Railway | Nixpacks con npm install && npm run build y luego npm start, con reinicio automático si falla. Variables: NODE_ENV, PORT, FRONTEND_URL, MONGODB_URI, JWT_SECRET, JWT_EXPIRES_IN, ML_SERVICE_URL, WEBAUTHN_* y RATE_LIMIT_*. |
| Predictor | Railway | Procfile con uvicorn main:app --host 0.0.0.0 --port $PORT y Python 3.11. |
| Base de datos | MongoDB Atlas | Base fabi_bd. Se recomienda permitir conexiones solo desde las IPs de salida del backend y evitar 0.0.0.0/0. |
Regla de oro: los valores de las variables se cargan solo en los paneles de Railway y Vercel (o con railway variables set, tomándolos de la terminal) y nunca se escriben en el repositorio. Si un secreto llega a publicarse alguna vez, hay que rotarlo: borrarlo del archivo no alcanza.
Prototipo funcional. La parte de clases, IMC, orientación por síntomas, roles y panel docente funciona de punta a punta. Se verificó en local el 22/10/2026: instalación, build del frontend y del backend, registro e ingreso por API, clases, IMC, predicción y panel docente.
En producción: el frontend está publicado en www.saludadultomayor.org. Al 22/10/2026, los servicios de backend y de predicción en Railway no responden (Railway contesta Application not found). Por eso, en el sitio publicado no funcionan el ingreso, el registro, el listado de clases ni la orientación hasta que se vuelvan a desplegar.
Pendiente y limitaciones conocidas:
faceRecognition.service.ts ya compara descriptores faciales de 128 dimensiones (distancia euclidiana con umbral de 0,6). Falta calcular esos descriptores en el navegador con el modelo face_recognition (ya incluido en frontend/public/models) y conectar el servicio al ingreso facial./admin, pero esa página todavía no existe; por ahora la gestión de usuarios se hace por API.npm run seed falla porque los usuarios de demostración no tienen cedula, que es obligatoria. Además, 14 de los 15 videos de seedClases.ts ya no existen en YouTube, por eso sus miniaturas aparecen grises.docker-compose.yml. La imagen del backend no compila porque el Dockerfile usa npm ci sin un lockfile propio. Por ahora conviene seguir los pasos manuales de arriba.Ronald Cipagauta · koptup.com · github.com/ronalc90
Distribuido bajo la licencia MIT. Ver LICENSE.