Imported from carolacodes/tu-turnito (
AGENTS.md). Install upstream withnpx skills add carolacodes/tu-turnito. Copyright stays with the author.
cat > /mnt/user-data/outputs/CLAUDE.md << 'EOF'
Tu Turnito — Agente de Codificación
Qué es este proyecto
SaaS de turnos con cobro de seña para emprendedores argentinos (tatuadores, peluquerías, esteticistas, etc.). Desarrollado por una sola persona (Carola). MVP en curso — cada decisión debe priorizar velocidad de entrega y simplicidad sobre arquitectura perfecta.
Stack tecnológico
- Frontend: Vite + React (JavaScript, no TypeScript)
- Backend: Node.js + Express.js (JavaScript)
- Base de datos: Supabase (PostgreSQL + Auth + Storage + RLS)
- Pagos: Mercado Pago SDK oficial (
mercadopagonpm) — Checkout Pro, flujo OAuth multi-tenant - Emails: Resend
- Hosting: Railway (backend) + Vercel (frontend) — pendiente de confirmar
Comandos del proyecto
# Frontend
cd frontend
npm run dev # servidor de desarrollo
npm run build # build de producción
npm run preview # previsualizar build
# Backend
cd backend
npm run dev # nodemon para desarrollo
npm start # producción
npm run db:types # generar tipos desde Supabase (si se agrega)
Estructura de carpetas
tu-turnito/
├── frontend/ # Vite + React
│ ├── src/
│ │ ├── pages/ # una carpeta por ruta principal
│ │ ├── components/ # componentes reutilizables
│ │ ├── hooks/ # custom hooks
│ │ ├── services/ # llamadas al backend (fetch/axios)
│ │ └── context/ # AuthContext y otros globales
│ └── .env.local
│
├── backend/ # Express.js
│ ├── src/
│ │ ├── routes/ # un archivo por recurso (turnos.js, pagos.js, etc.)
│ │ ├── controllers/ # lógica de cada endpoint
│ │ ├── services/ # lógica de negocio (mercadopago, resend, supabase)
│ │ ├── middlewares/ # auth, validación, errores
│ │ └── lib/ # clientes inicializados (supabaseAdmin, mpClient)
│ ├── .env
│ └── index.js
│
└── AGENTS.md
Supabase: qué hace Supabase vs qué hace el código
Supabase maneja (no reimplementar en código):
- Auth completo: registro, login, recupero de contraseña, OAuth de Google
- Row Level Security (RLS): políticas de acceso por
profile_id, definidas en la DB - Storage: fotos de perfil y logos de negocio
- Realtime: suscripciones a cambios en tabla
turnos(para la agenda en vivo)
El backend de Express maneja (no delegar a Supabase):
- Lógica de reserva: validar disponibilidad, detectar solapamientos de horarios
- OAuth flow de Mercado Pago por emprendedor (multi-tenant)
- Creación de preferencias de pago con el access_token del emprendedor
- Webhook de confirmación de pago de Mercado Pago
- Envío de emails con Resend
- Refresh de tokens de MP vencidos
Modelo multi-tenant — regla crítica
Cada emprendedor tiene su propia cuenta de Mercado Pago conectada via OAuth.
- El
access_tokende MP se guarda en la tablaprofilesasociado alprofile_id - Nunca usar el access_token propio de la app para crear pagos de emprendedores
- Siempre buscar el
mp_access_tokendel emprendedor antes de crear una preferencia - Verificar
mp_token_expires_aty hacer refresh si venció antes de cualquier operación de pago
Tablas principales en Supabase
profiles— extiendeauth.users, datos del emprendedor + tokens de MP + planservicios— servicios que ofrece cada emprendedordisponibilidad— horarios disponibles por día de semanaturnos— reservas con estado:pendiente | señado | confirmado | cancelado | completadopagos— historial de pagos, separado de turnos para escalar
Todas las tablas tienen profile_id como FK y RLS activado.
Convenciones de código
- JavaScript puro, sin TypeScript — no agregar TS en este proyecto
- Archivos en kebab-case:
turno-controller.js,mp-service.js - Variables y funciones en camelCase
- Constantes globales en UPPER_SNAKE_CASE
- Un controller por recurso, la lógica de negocio va en services (no en routes)
- Errores siempre con
try/catchy respuesta{ error: mensaje }con el status HTTP correcto - Variables de entorno: nunca hardcodear tokens ni keys, siempre desde
process.env
Reglas inamovibles
- No usar TypeScript — el proyecto es JavaScript puro
- No instalar librerías nuevas sin preguntar — el proyecto prioriza dependencias mínimas
- No modificar el esquema de Supabase desde código — los cambios de schema se hacen en el dashboard de Supabase o con migraciones explícitas
- No exponer el
mp_access_tokendel emprendedor al frontend — ese token solo vive en el backend - RLS siempre activado en tablas nuevas — nunca crear una tabla sin definir su política
Contexto de negocio relevante
- El cliente final (quien reserva) NO tiene cuenta en la app — solo ingresa nombre, email y teléfono
- El emprendedor SÍ tiene cuenta (Supabase Auth) y un panel de administración
- La URL pública de cada emprendedor es
dominio.com/[slug]— el slug es único por emprendedor - El cobro es de una seña (porcentaje del servicio), no el total
- El monto de la seña lo define el emprendedor por servicio (
seña_porcentajeen tablaservicios) - Los estados del turno siguen este flujo:
pendiente → señado → confirmado → completado - Argentina: moneda ARS, zona horaria America/Argentina/Buenos_Aires
Fase actual: MVP
Funcionalidades incluidas en esta fase:
- Auth del emprendedor (Supabase)
- CRUD de servicios y horarios
- Vista pública del emprendedor (
/[slug]) - Flujo de reserva + cobro de seña con MP
- Webhook de confirmación de pago
- Email de confirmación al cliente (Resend)
- Panel de agenda del emprendedor
Funcionalidades fuera del MVP (no implementar aún):
- WhatsApp automático
- IA para respuestas
- Suscripciones/planes