{"id":50497590,"url":"https://github.com/moisesvalero/fisionova","last_synced_at":"2026-06-02T09:02:45.944Z","repository":{"id":361140116,"uuid":"1252140969","full_name":"moisesvalero/fisionova","owner":"moisesvalero","description":"Landing completa de una clinica local ficticia con reservas con IA","archived":false,"fork":false,"pushed_at":"2026-05-29T11:06:03.000Z","size":878,"stargazers_count":1,"open_issues_count":5,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T11:18:42.652Z","etag":null,"topics":["nextjs","react","supabase","typescript","vercel"],"latest_commit_sha":null,"homepage":"https://proyecto-ia-recepcionista.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moisesvalero.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-28T08:21:58.000Z","updated_at":"2026-05-29T11:06:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/moisesvalero/fisionova","commit_stats":null,"previous_names":["moisesvalero/fisionova"],"tags_count":null,"template":false,"template_full_name":"moisesvalero/next-agent-template","purl":"pkg:github/moisesvalero/fisionova","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moisesvalero%2Ffisionova","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moisesvalero%2Ffisionova/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moisesvalero%2Ffisionova/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moisesvalero%2Ffisionova/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moisesvalero","download_url":"https://codeload.github.com/moisesvalero/fisionova/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moisesvalero%2Ffisionova/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33814318,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nextjs","react","supabase","typescript","vercel"],"created_at":"2026-06-02T09:02:44.852Z","updated_at":"2026-06-02T09:02:45.925Z","avatar_url":"https://github.com/moisesvalero.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FisioNova Clinica, recepcionista IA para fisioterapia\n\n[![Demo en Vercel](https://img.shields.io/badge/Demo-Vercel-black?logo=vercel)](https://proyecto-ia-recepcionista.vercel.app/)\n![Next.js](https://img.shields.io/badge/Next.js-16-black?logo=nextdotjs)\n![React](https://img.shields.io/badge/React-19-61DAFB?logo=react\u0026logoColor=111)\n![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?logo=typescript\u0026logoColor=white)\n![License](https://img.shields.io/badge/license-CC--BY--NC--4.0-lightgrey)\n\nDemo publica para portfolio tecnico: una web app de una clinica de fisioterapia ficticia con recepcionista IA, solicitud de citas, agenda privada para el medico y confirmaciones por email.\n\n**Demo online:** [https://proyecto-ia-recepcionista.vercel.app/](https://proyecto-ia-recepcionista.vercel.app/)\n\n![Captura de FisioNova Clinica](docs/images/home-screenshot.png)\n\n\u003e FisioNova Clinica no es una clinica real. Es un proyecto de portfolio para demostrar producto, UX, frontend, backend ligero e integracion con IA. El chat incluye una barrera de seguridad: ante urgencias, diagnosticos, medicacion o sintomas serios, informa de que es una demo ficticia y deriva a urgencias o a un profesional sanitario real.\n\n## Que demuestra\n\n- Landing completa de una clinica local ficticia, con hero visual, tratamientos, equipo, contacto, FAQ y politica de cookies.\n- Chat con Virgi, recepcionista IA, integrado en la web y ampliable en modal.\n- Integracion opcional con OpenAI para interpretar mensajes y proponer huecos.\n- Flujo seguro de citas: la IA no confirma citas finales, crea una solicitud pendiente.\n- Panel privado `/medico` protegido por PIN.\n- Calendario operativo tipo agenda, con horario fijo 10:00-19:00, filtro por profesional, click en citas, ficha del paciente, acciones y movimiento por drag and drop.\n- Gestion manual desde `/medico`: crear, modificar, cancelar y confirmar citas sin depender al cien por cien de la IA.\n- Panel enfocado a recepcion: estados operativos, recordatorios por email, bloqueos manuales, no presentado, pago pendiente y cita finalizada.\n- Tratamientos con tiempo de sesion y lista de espera para recolocar pacientes que quieren venir antes cuando se libera un hueco.\n- Enlaces firmados en emails para que el paciente pueda confirmar o cancelar sin entrar al panel privado.\n- Emails transaccionales con Resend solo desde el panel privado.\n- Modo demo sin base de datos, mas opcion Supabase para persistencia real.\n- SEO tecnico: metadata, sitemap, robots, manifest, Open Graph, JSON-LD y `llms.txt`.\n- Verificacion con TypeScript, ESLint, Prettier, Vitest, build y audit.\n\n## Stack\n\n- Next.js 16, App Router y React 19.\n- TypeScript estricto.\n- Tailwind CSS 4.\n- Componentes estilo shadcn con `Button` y utilidad `cn()`.\n- Zod para validar variables de entorno y payloads.\n- OpenAI Responses API para la recepcionista.\n- Resend para emails de confirmacion, cancelacion y cambios.\n- Supabase opcional para guardar citas en produccion.\n- Vitest, Testing Library, ESLint y Prettier.\n\n## Flujo de cita\n\n1. El paciente habla con Virgi.\n2. Si no cuenta que le duele, Virgi pregunta antes de mostrar huecos.\n3. Si detecta el motivo, asigna tratamiento: general, deportiva o postural.\n4. La web muestra huecos disponibles.\n5. El paciente deja sus datos.\n6. Se crea una cita `pending`.\n7. El medico entra en `/medico`, revisa el calendario y confirma, mueve o cancela.\n8. Si una cancelacion o cambio libera un hueco, el panel propone pacientes marcados como \"quiere venir antes\".\n9. Recepcion puede marcar esperando respuesta, pago pendiente, no presentado, finalizada o enviar recordatorio.\n10. Solo al confirmar/cambiar/cancelar/crear/recordar desde el panel privado se llama a `/api/email`.\n\n## Seguridad y limites actuales\n\nIncluido:\n\n- `.env*` ignorado por Git, excepto `.env.example`.\n- Validacion centralizada de env vars en `src/lib/env.ts`.\n- OpenAI y Resend solo se usan desde rutas server-side.\n- `/api/appointments` protege lectura y cambios con `DOCTOR_DASHBOARD_PIN`.\n- `/api/email` protege el envio con `DOCTOR_DASHBOARD_PIN`.\n- Rate limit ligero en memoria para `/api/receptionist` y POST publico de `/api/appointments`.\n- Limites de longitud en mensajes, datos de paciente y payloads de email.\n- Headers de seguridad en `next.config.ts`.\n- `/medico` tiene `noindex` y `robots.ts` bloquea `/api/` y `/medico`.\n- JSON-LD se serializa escapando `\u003c`.\n\nPendiente para produccion real:\n\n- Cambiar `DOCTOR_DASHBOARD_PIN`, no usar `1234`.\n- Activar Supabase si quieres persistencia real de citas.\n- Configurar reglas/RLS y backups si se usa Supabase.\n- Anadir proteccion perimetral real si el proyecto recibe trafico: Vercel Firewall, WAF, Turnstile, captcha o rate limit persistente.\n- Rotar cualquier API key que se haya pegado en chats, capturas o commits.\n- Revisar textos legales con un profesional si se va a usar comercialmente.\n\n## Arranque local\n\n```bash\nnpm install\ncp .env.example .env.local\nnpm run dev\n```\n\nAbre `http://localhost:3000`.\n\nPanel privado local:\n\n```text\nhttp://localhost:3000/medico\nPIN demo: 1234\n```\n\n## Variables de entorno\n\nCopia `.env.example` a `.env.local` y rellena solo lo necesario.\n\n```env\nNEXT_PUBLIC_APP_URL=http://localhost:3000\n\n# OpenAI opcional\nOPENAI_API_KEY=\nOPENAI_MODEL=gpt-5.4-nano\n\n# Supabase opcional\nNEXT_PUBLIC_SUPABASE_URL=\nNEXT_PUBLIC_SUPABASE_ANON_KEY=\nSUPABASE_SERVICE_ROLE_KEY=\n\n# Panel privado\nDOCTOR_DASHBOARD_PIN=1234\nAPPOINTMENT_ACTION_SECRET=\n\n# Resend opcional\nRESEND_API_KEY=\nRESEND_FROM_EMAIL=onboarding@resend.dev\nRESEND_REPLY_TO_EMAIL=\n```\n\nSin `OPENAI_API_KEY`, se usa fallback local basado en reglas. Sin `SUPABASE_SERVICE_ROLE_KEY`, las citas viven en memoria durante la sesion del servidor. Sin `RESEND_API_KEY`, los emails se simulan.\n\n## Despliegue en Vercel\n\n1. Importa el repositorio en Vercel.\n2. Configura como minimo:\n   - `NEXT_PUBLIC_APP_URL=https://tu-dominio.vercel.app`\n   - `DOCTOR_DASHBOARD_PIN=un-pin-largo-no-obvio`\n3. Para IA real:\n   - `OPENAI_API_KEY`\n   - `OPENAI_MODEL=gpt-5.4-nano` o el modelo gratuito/disponible que quieras probar.\n4. Para emails reales:\n   - `RESEND_API_KEY`\n   - `RESEND_FROM_EMAIL`\n   - `RESEND_REPLY_TO_EMAIL` si quieres que las respuestas vayan a otra cuenta.\n5. Para persistencia real:\n   - `NEXT_PUBLIC_SUPABASE_URL`\n   - `NEXT_PUBLIC_SUPABASE_ANON_KEY`\n   - `SUPABASE_SERVICE_ROLE_KEY`\n   - Ejecuta `supabase/appointments.sql` en tu proyecto Supabase.\n\n### Entregabilidad de emails\n\nPara reducir la probabilidad de spam en Resend:\n\n- Usa un dominio verificado con SPF y DKIM activos.\n- Mantén DMARC publicado en DNS. Para empezar: `v=DMARC1; p=none; rua=mailto:tu-email@tu-dominio.com;`.\n- Envía desde una cuenta real del dominio, por ejemplo `FisioNova \u003ccitas@moisesvalero.es\u003e`, y configura `RESEND_REPLY_TO_EMAIL`.\n- Evita mezclar emails transaccionales con llamadas comerciales agresivas. El email de cita mantiene el portfolio como firma pequeña.\n- En Resend, revisa cada envío en **Emails \u003e Insights** para confirmar que pasan SPF, DKIM y DMARC.\n\n6. Ejecuta antes:\n\n```bash\nnpm run verify\n```\n\n## Scripts\n\n```bash\nnpm run dev              # servidor local\nnpm run build            # build de produccion\nnpm run start            # servir build\nnpm run lint             # ESLint\nnpm run check            # TypeScript sin emitir\nnpm run format           # formatear con Prettier\nnpm run format:check     # comprobar formato\nnpm test                 # tests unitarios\nnpm run audit            # npm audit high+\nnpm run verify           # formato, lint, tipos, tests, build y audit\nnpm run design:audit     # auditoria visual con Impeccable\n```\n\n## Estructura principal\n\n```text\nsrc/\n  app/\n    api/appointments/     # citas, agenda privada y acciones\n    api/email/            # emails protegidos por PIN\n    api/receptionist/     # chat IA y fallback local\n    medico/               # panel privado\n  components/\n    receptionist/         # landing, chat, calendario y panel medico\n    legal/                # cookies\n    seo/                  # JSON-LD\n    ui/                   # componentes base\n  lib/\n    receptionist/         # agenda, datos demo, emails y store\n    env.ts                # validacion de entorno\n    rate-limit.ts         # rate limit demo en memoria\nsupabase/\n  appointments.sql        # esquema opcional\n```\n\n## Licencia\n\nEste proyecto esta publicado bajo Creative Commons Attribution-NonCommercial 4.0 International (`CC-BY-NC-4.0`).\n\nPuedes estudiar, compartir y adaptar el codigo con atribucion, pero no puedes usarlo con fines comerciales, revenderlo, desplegarlo para un cliente, ofrecerlo como SaaS, white-label o integrarlo en un producto/servicio de pago sin permiso escrito del autor.\n\nVer [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoisesvalero%2Ffisionova","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoisesvalero%2Ffisionova","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoisesvalero%2Ffisionova/lists"}