Stack tecnológico
| Capa | Tecnología |
|---|---|
| Frontend | Next.js 16 (App Router, Turbopack), React 19, Tailwind CSS v4 |
| Componentes UI | shadcn/ui v4 (estilo base-nova) |
| API | Fastify 5, TypeScript |
| Base de datos | Neon serverless Postgres, Drizzle ORM |
| Autenticación | Clerk (organizaciones habilitadas) |
| Facturación | Stripe |
| Validación | Zod |
| IA | OpenAI GPT-4 |
Estructura del monorepo
PoolPuma usa un monorepo con pnpm workspaces + Turborepo:apps/web: Frontend Next.js con App Routerapps/api: API REST con Fastifyapps/docs: Este sitio de documentación (Mintlify)packages/db: Esquema Drizzle ORM compartido y utilidades de base de datos
Multi-inquilino
PoolPuma es multi-inquilino usando organizaciones de Clerk. Cada organización representa una empresa de servicio de piscinas y puede tener múltiples sucursales (regiones de servicio).Los datos de la organización y los miembros de Clerk se sincronizan con la base de datos en el primer acceso mediante la utilidad
ensureOrgSynced(). Esto evita depender únicamente de webhooks y maneja casos límite como entregas de webhooks fallidas.Esquema de base de datos
La base de datos tiene 18 tablas organizadas en estos dominios:- Inquilinos: organizations, stores, memberships, store_access
- CRM: customers, properties, pool_profiles
- Operaciones: routes, route_stops, technician_assignments, service_visits, service_reports
- Facturación: plans, subscriptions, invoices
- Inventario: inventory_items, equipment_assets
- Sistema: audit_events
Flujo de autenticación
- El usuario inicia sesión mediante Clerk
- El middleware de Clerk protege todas las rutas
/dashboard - En el primer acceso al dashboard,
ensureOrgSynced()sincroniza la organización y sus miembros con la base de datos - Todas las consultas posteriores están limitadas a la organización del usuario