Arquitectura del sistema
Cómo está construido Amalfi por dentro: las piezas, dónde viven los datos y cómo fluyen los pagos.
En resumen
Una para tus clientas (reservar y pagar), una para tu equipo (recepción, instructor, admin) y una interna de Amalfi.
Cada estudio tiene sus datos aislados de los demás. Nadie de otro estudio puede ver tu información.
El dinero de tus clientas llega directo a tu cuenta vía Wompi. Amalfi te cobra aparte su suscripción.
El detalle técnico de abajo es para el equipo de desarrollo. No hace falta entenderlo para usar el producto.
Forma general — multi-repo
Backend monolito Laravel (API + Filament) en su propio repo, más dos frontends Next.js independientes y los SDKs propios de Wompi. No es monorepo ni Inertia: cada frontend tiene su SSR, NextAuth e i18n.
| Repo | Tech | Rol |
|---|---|---|
| amalfi-core | Laravel 13 · PHP 8.4 | API backend (monolito) + Filament admin |
| amalfi-dashboard | Next.js 16 · React 19 | Back Office (operadores del estudio) |
| amalfi-web | Next.js 16 · React 19 | Front Office (clientes finales) |
| wompi-laravel · wompi-sdk-php | PHP | SDK / integración Wompi propia |
Diagrama de componentes
Tres audiencias entran por sus frontends; el Core Laravel orquesta datos, cache y storage en Laravel Cloud, y se integra con los proveedores externos de pago, payout y email. Fuente: ASM Amalfi V1.
Multi-tenancy — row-based (stancl/tenancy)
Single-database, row-scoping por studio_id vía el trait BelongsToTenant. La resolución de tenant en Back Office es por usuario autenticado (no por dominio). Camino soportado a DB dedicada por estudio cuando uno crezca.
[estudio].amalfi.appdashboard.amalfi.appadmin.amalfi.appEl Front Office se sirve bajo subdominio dinámico por estudio, con dominio custom configurable. Back Office y Admin Panel son dominios fijos.
Dos integraciones de dinero separadas: Wompi procesa el pago de la alumna al estudio (el estudio recibe el 100%); Stripe cobra a los estudios la suscripción + comisión de Amalfi, configurable por estudio desde Filament.
Aislamiento de tenants — cómo funciona
Single-database, shared schema con aislamiento por studio_id. stancl/tenancy maneja resolución de tenant, scoping (vía Global Scopes de Eloquent) y bootstrapping en jobs/colas. La resolución en Back Office es por usuario autenticado (no por dominio). El superadmin puede impersonar cualquier estudio con flag auditado. Tests automatizados verifican que un usuario de un estudio no accede a datos de otro.
En Back Office el tenant se resuelve por el usuario autenticado, no por subdominio. stancl/tenancy lo inicializa para la request y los jobs.
Los modelos tenant aplican el trait BelongsToTenant. El scope se inyecta en cada query (joins, subqueries y eager loads incluidos).
El panel Filament puede impersonar cualquier estudio saltándose los scopes, con flag auditado. Camino soportado: graduar un estudio a su propia DB.
Decisiones de arquitectura (del repo)
Sesiones/cache en Redis, storage en R2 → sin disco local, habilita escalado horizontal. Hoy corre en drivers database; mover a Redis + R2 es cambio de configuración, no de código.
Lo que no es necesario para la respuesta inmediata corre en job encolado (email de confirmación, recibos, webhooks de Wompi).
app/Modules/ organizado en buckets Central/ (staff Amalfi) y Tenant/ (datos del estudio), con generadores propios (MakeModuleCommand y demás).
composer check = Pint + PHPStan (level max) + Rector + composer-normalize + Pest. Requisitos: PHP 8.4, PostgreSQL, Node 22, Composer 2.
Flujos críticos
- 1 Alumna elige clase en el Front Office (amalfi-web)
- 2 API valida créditos disponibles con el scope de tenant
- 3 Reserva con pessimistic lock sobre el cupo de la sesión
- 4 Job en queue: email de confirmación vía Resend
- 5 Clase aparece en "Mis reservas" inmediatamente
- 1 Alumna selecciona paquete en el Front Office
- 2 API crea la sesión de pago y redirige a Wompi hosted checkout
- 3 Alumna paga con tarjeta en el widget de Wompi
- 4 Wompi → webhook firmado → job ProcessWompiWebhook
- 5 Job activa el client_package + Resend recibo de compra
- 1 Scheduler calcula comisiones sobre las transactions del mes
- 2 Job GenerateMonthlyInvoice por estudio
- 3 Stripe: suscripción fija en su ciclo + comisión los días 3–5
- 4 Configurable por estudio desde Filament (superadmin)
- 5 amalfi_invoices actualiza status → paid