Synaplan
Open-source AI platform for companies: self-hosted AI agents, GDPR-compliant chatbot widget, RAG knowledge base, WhatsApp and Outlook AI, MCP, multi-model routing. Docker, Kubernetes or hosted in Germ
Gestión de la clínica dental: agenda, pacientes, caja y cotizaciones.
Translation pending
BusinessTypeScript · HTMLGitHub @angelmieses004-sketchOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Sistema de gestión para una clínica dental. Incluye:
Stack: Next.js 16 (App Router), TypeScript, Tailwind CSS 4, Supabase (Postgres, Auth, Storage y RLS), Motion, Recharts, Zod, @react-pdf/renderer y ExcelJS.
El prototipo original y las instrucciones del bot están en referencia/, solo como referencia de reglas de negocio.
Requisito: Node 22 o superior.
npm install
npm run dev # http://localhost:3000
Mientras .env.local no tenga las claves de Supabase, la app arranca en vista previa:
/login eliges un rol (Administrador, Odontólogo o Recepción).npm run dev vuelven los datos originales. Ajustes → Datos de ejemplo → Reiniciar hace lo mismo.| Comando | Qué hace |
|---|---|
npm run dev | Servidor de desarrollo |
npm run build && npm start | Compilación y servidor de producción |
npm test | Pruebas de las reglas críticas (saldo, recordatorios, citas repetidas, choque de horario, odontograma, horarios libres) |
npm run typecheck | Revisión de tipos |
npm run seed:generar | Regenera supabase/seed.sql desde src/datos/ejemplo.ts |
npm run superadmin -- correo "Nombre" | Crea la cuenta de superadministrador de Rido |
npm run probar:rls | Prueba las políticas RLS contra tu proyecto de Supabase |
Crear el proyecto en supabase.com → New project.
Copiar las claves en .env.local. Están en Project Settings → API Keys:
| Variable | Clave |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | URL del proyecto |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY | publishable (o anon public) |
SUPABASE_SECRET_KEY | secret (o service_role). Solo servidor, nunca en git |
Crear las tablas. En SQL Editor ejecuta en orden:
supabase/migrations/20261021000001_base.sql (clínica, equipo, roles, auditoría)supabase/migrations/20261021000002_operacion.sql (pacientes, citas, recordatorios, caja, cotizaciones)supabase/migrations/20261021000003_clinico.sql (panorámicas, odontograma, IA y buckets privados)supabase/migrations/20261022000004_inventario.sql (inventario y sus movimientos)supabase/seed.sql (opcional: datos de ejemplo con es_ejemplo = true)Con la CLI también se puede: npx supabase login, npx supabase link --project-ref <ref> y npx supabase db push.
Configurar Auth:
Sign In / Providers → Email: desactiva "Allow new users to sign up". Solo entra quien fue invitado.
URL Configuration:
http://localhost:3000 para probar.<tu dominio>/** a Redirect URLs.Emails → Templates: en Invite user y Reset password, cambia el enlace por:
{{ .SiteURL }}/auth/confirmar?token_hash={{ .TokenHash }}&type=invite&siguiente=/cuenta/contrasena
En Reset password usa .
| Rol | Puede |
|---|---|
| Administrador | Todo, incluidos el equipo, el catálogo, los ajustes y la actividad (auditoría) |
| Odontólogo | Agenda, todos los pacientes, cotizaciones, odontograma y panorámicas. Sin caja |
| Recepción | Agenda, pacientes, recordatorios, caja, cotizaciones e inventario. No ve radiografías, solo sabe si el paciente tiene |
En el inventario, todo el equipo puede poner y sacar existencias (queda en el historial quién lo hizo). Solo administración y recepción crean, editan o borran artículos.
/api/panoramicas/[id]: revisa el rol y redirige a una URL firmada que vence en 2 minutos. Nunca hay URLs públicas.Flujo existente: "Clínica Dental · Bot de recordatorios WhatsApp" (ID tA98h2EQOxFvT49K).
Todos piden Authorization: Bearer <N8N_TOKEN>. Pon un valor largo y aleatorio en N8N_TOKEN. En la vista previa el token es vista-previa.
| Método y ruta | Para qué |
|---|---|
GET /api/n8n/recordatorios | Recordatorios que deben salir hoy: avisos del mismo día, avisos de 3 días antes y fallidos para reintentar |
POST /api/n8n/recordatorios/resultado | Marca cada uno como enviado o fallido |
POST /api/n8n/respuestas | Preparado y apagado. Recibe «Confirmo» o «Aplazar» (N8N_RESPUESTAS_ACTIVAS=true) |
Respuesta de GET /api/n8n/recordatorios:
{ "fecha": "2026-10-21", "total": 2, "recordatorios": [
{ "recordatorioId": "…", "citaId": "…", "tipo": "previo", "telefono": "18095550111", "nombre": "Ana",
"fecha": "sábado, 24 de octubre", "hora": "9:00 a. m.", "doctor": "Dra. Laura Peña",
"clinica": "Clínica Dental Sonrisa", "direccion": "Calle del Sol #45, Santiago", "mensaje": "…" } ],
"sinTelefono": [] }
Cuerpo de POST /api/n8n/recordatorios/resultado:
{ "resultados": [ { "recordatorioId": "…", "estado": "enviado" },
{ "recordatorioId": "…", "estado": "fallido", "error": "Número sin WhatsApp" } ] }
45 7 * * *.America/Santo_Domingo (Settings del flujo → Timezone).https://<tu-dominio>/api/n8n/recordatorios.Authorization: Bearer <N8N_TOKEN>.recordatorios.Plantilla: recordatorio_cita_3dias si tipo es previo, recordatorio_cita_hoy si es hoy. Usa un nodo If o una expresión.
Variables:
| Variable | Campo |
|---|---|
{{1}} | nombre |
{{2}} | fecha |
{{3}} | hora |
{{4}} | doctor |
{{5}} | clinica |
{{6}} | direccion |
Destinatario: telefono.
En Settings del nodo, activa Continue On Fail para que un error no detenga a los demás.
{ recordatorioId, estado: $json.error ? "fallido" : "enviado", error: $json.error?.message }.resultados.https://<tu-dominio>/api/n8n/recordatorios/resultado, con la misma credencial y el cuerpo { "resultados": … }.Lo que el bot no pueda enviar aparece en Recordatorios → Fallidos para enviarlo a mano.
POST /api/n8n/respuestas:
{ "citaId", "respuesta": "confirmo" } → la cita pasa a confirmada.{ "citaId", "respuesta": "aplazar" } → devuelve 3 horarios libres del mismo odontólogo, dentro del horario de la clínica.{ "citaId", "respuesta": "aplazar", "eleccion": { "fecha", "hora" } } → mueve la cita y reprograma los recordatorios.N8N_RESPUESTAS_ACTIVAS=true.| Función | En la vista previa |
|---|---|
| Cotizaciones | El asistente responde con preguntas y respuestas fijas, como un FAQ. Arma la cotización solo con servicios del catálogo y sus precios exactos |
| Panorámicas | Apagadas por defecto (Ajustes → IA). Al activarlas, «Pedir sugerencia» marca zonas fijas para revisar |
Las sugerencias de panorámicas siempre llevan la etiqueta «Sugerencia, no es diagnóstico. Confirmar por el odontólogo». Nunca cambian el odontograma solas: el odontólogo acepta o descarta cada una.
Para usar un modelo real, solo se cambia src/lib/ia/asistente.ts y la llamada se hace desde el servidor. La clave va en .env.local y nunca en el navegador.
.env.local en Settings → Environment Variables. NEXT_PUBLIC_SITE_URL debe ser el dominio real.https://<tu-dominio>/demo.La vista previa en memoria es solo para demostrar en local. En Vercel, conecta Supabase.
src/
app/
(auth)/ login, recuperar, crear contraseña
(app)/ pantallas con barra lateral
resumen/ agenda/ recordatorios/ caja/ cotizaciones/ ajustes/
pacientes/[id]/clinico/ visor, comparador, odontograma, panel de pieza
demo/ demostración pública del bot
api/ panorámicas, comprobantes, Excel, PDF y endpoints de n8n
design/tokens.css ÚNICO archivo del sistema de diseño (oscuro y claro)
components/bona/ tarjetas, calendario, anillos, chips, mini gráficas…
components/ui/ formularios, diálogos, pestañas, menús y avisos
datos/ repo.ts (Supabase o memoria) y datos de ejemplo
lib/reglas/ reglas de negocio puras y probadas
lib/ia/ asistente (modo de prueba)
proxy.ts protege rutas y refresca la sesión
supabase/migrations/ SQL versionado con RLS
scripts/ superadmin, prueba de RLS y generador del seed
tests/ Vitest
npm run probar:rls (al cerrar la venta).type=recoveryCrear el superadministrador:
npm run superadmin -- [email protected] "Tu Nombre"
Imprime una contraseña temporal. Cámbiala desde «¿Olvidaste tu contraseña?».
Invitar al equipo desde Ajustes → Equipo.
Verificar la seguridad con npm run probar:rls. Crea usuarios temporales por rol, comprueba qué ve cada uno y los borra.