XHealtXperience is built around a strict multi-tenant model: every clinic that signs up gets its own siloed environment — its own database, its own users, its own patients, and its own configuration. No clinic can ever see or touch another clinic’s data. This isolation is enforced at the infrastructure level using the stancl/tenancy package (v3.x) and a path-based tenant identification strategy.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Arthurr23/XHealtXperience/llms.txt
Use this file to discover all available pages before exploring further.
How tenancy works: the two-database model
XHealtXperience maintains two distinct database layers that never overlap.Central database
The central database is the application’s backbone. It is defined byconfig/tenancy.php as the mysql connection and stores:
| Table | Purpose |
|---|---|
tenants | One row per registered clinic, including subscription metadata |
domains | Path-based “domains” (tenant IDs) linked to each tenant |
users | Central users only — the Super Admin lives here |
jobs | Laravel queued jobs |
cache | Application-level cache |
sessions | Central session storage |
Tenant databases
Each time a new clinic is registered, the platform provisions a dedicated SQLite (or MySQL) database namedtenant{id}.sqlite (or tenant{id} in MySQL). This database contains a full, isolated schema including:
users— clinic staff accounts (doctors, receptionists, administrators, auditors)pacientes— patient records with clinical filescitas— appointments and schedulingservicios,lineas_servicio,servicio_etapas— the clinic’s service cataloguepaciente_servicios,paciente_servicio_etapas— patient service execution and trackingquirofanos,salas,procedimientos_quirurgicos— surgical suite managementaudit_logs— full audit trail for HIPAA-style compliancetenant_settings— per-clinic security and configuration (see Clinic Settings)roles,permissions— Spatie roles and permissions seeded at clinic creation
Path-based tenancy and routing
XHealtXperience usesInitializeTenancyByPath — not subdomain-based tenancy. This means every tenant-scoped URL is prefixed with the clinic’s ID:
routes/tenant.php and are wrapped by the InitializeTenancyByPath middleware:
/{tenantId}/..., the middleware reads the first URL segment, looks up the matching tenant in the central domains table, and switches the active database connection to that clinic’s isolated database. Every subsequent Eloquent query in the request lifecycle runs against the tenant’s own database.
Central routes
Central routes are defined inroutes/web.php and carry no tenant prefix. The Super Admin panel is protected by auth, two_factor, and role:Super Admin middleware:
The Tenant model
TheApp\Models\Tenant class extends Stancl\Tenancy\Database\Models\Tenant and declares custom columns so the package treats them as real table columns rather than JSON data:
| Column | Type | Description |
|---|---|---|
id | string | URL-safe slug used as the path prefix (e.g. clinica-norte) |
nombre_clinica | string | Human-readable display name |
codigo_clinica | string(5) | Short prefix (e.g. STL) used to generate sequential patient codes |
email_contacto | string | Billing/contact email |
telefono_contacto | string(20) | Optional contact phone |
plan | enum | Subscription plan (basico, pro, premium, personalizado) |
limite_cuentas | unsignedInteger | Maximum number of staff accounts the clinic may create |
estado | enum | Operational status (activa or suspendida) |
fecha_inicio_suscripcion | date | Subscription start date |
Subscription plans
Each plan carries a suggestedlimite_cuentas value, defined in Tenant::LIMITES_POR_PLAN. The Super Admin may override this number at any time for any clinic.
| Plan | Default account limit | Intended for |
|---|---|---|
basico | 5 | Small single-doctor practices |
pro | 20 | Mid-size multi-specialty clinics |
premium | 50 | Large clinic networks |
personalizado | Configurable (1–1000) | Special contracts |
Clinic status (estado)
A clinic’s estado column accepts exactly two values enforced by a database CHECK constraint:
activa— the clinic is operational; staff can log in and use all features.suspendida— the clinic is suspended; the Super Admin can toggle this from the dashboard at any time.
Account usage helpers
TheTenant model exposes two helper methods for tracking how many staff accounts a clinic has consumed. Both methods require tenancy to already be initialized for the target tenant, because User lives in the tenant database.
Reserved tenant IDs
The following IDs can never be used as a tenant
id because they conflict with central application routes:panel-global · login · logout · register · apiThe SuperAdminController::store() method enforces this with a Rule::notIn() validation rule. Attempting to register a clinic with any of these IDs will return a validation error.Super Admin Panel
Manage clinic registration, account limits, suspension, and cross-clinic user creation from the central panel.
Clinic Settings
Configure per-clinic session timeouts, login lockout thresholds, and the visitor self check-in token.