06 — Stack tecnológico · COMAL
Decisión de arquitectura
PWA monorepo full-stack orientada a velocidad de MVP y operaciones de reserva con integridad temporal.
| Capa | Elección | Justificación |
|---|---|---|
| Frontend | Next.js 15 (App Router) + TypeScript | SSR landing SEO + app autenticada; PWA via serwist/next-pwa |
| UI | Tailwind CSS v4 + tokens Paper exportados | Paridad con design tokens |
| Componentes | Radix UI primitives + estilos propios | Accesibilidad de base |
| API | tRPC o Route Handlers REST | tRPC si monorepo TS puro; REST si apps móviles después |
| Auth | Auth.js (NextAuth v5) | Email magic link + Google; roles en JWT/session |
| DB | PostgreSQL (Neon) | Exclusion constraints para slots; branching previews |
| ORM | Drizzle ORM | Tipado, migraciones SQL claras |
| Cache / locks | Redis (Upstash) | Hold de slots, rate limit |
| Pagos | Stripe Checkout/PaymentIntents + Billing | PCI SAQ-A; suscripciones membresía |
| Resend | Transaccional ES templates | |
| SMS (opc.) | Twilio | Recordatorios check-in |
| Maps | Mapbox GL | Listado geo |
| Storage | S3 compatible (R2/S3) | Fotos y certificados firmados |
| Hosting | Vercel | Edge + serverless; ES region |
| Observability | Sentry + Axiom/OpenTelemetry | Errores y traces |
| Analytics | PostHog | Product analytics + feature flags |
| CI | GitHub Actions | lint, typecheck, e2e Playwright |
Por qué no X
| Alternativa | Motivo de descarte (v1) |
|---|---|
| React Native | Coste dual sin validar demanda |
| Firebase | Menos control de exclusion constraints de booking |
| Supabase Auth only | Viable; Auth.js + Neon da más control de modelo |
| MongoDB | Debil para rangos temporales concurrentes |
Integridad de reservas
- Hold en Redis 10 min (v1.1) o
pending_paymentcon TTL EXCLUDEgist en Postgres al confirmar- Webhook Stripe idempotente →
confirmed - Job de limpieza de pending expirados
Entornos
local·preview(Neon branch) ·staging·production
Estimación de equipo mínimo implementación
2 fullstack, 1 designer part-time, 1 ops/product part-time — 10–14 semanas MVP ciudad piloto.