> **Propósito:** explicar cómo está construido el frontend. Este documento, junto con [UI system](./ui-system.md) y [UI patterns](./ui-patterns.md), forma la fuente de verdad (SSOT) de frontend/UI.
## 1. Stack
El frontend usa React 19, TypeScript estricto, React Router, TanStack Query, React Hook Form, Axios, Tailwind CSS v4, Shadcn/UI y `@repo/rdx-ui`.
-`shared/adapters`: transforma DTOs en entidades de frontend.
-`shared/entities`: modelos consumidos por la aplicación.
-`shared/hooks`: queries, mutations y query keys de TanStack Query.
-`controllers`: orquestación funcional, formularios, navegación y efectos.
-`page controllers`: componen el estado completo de una pantalla.
-`Page`: conecta controller y componentes; debe tener poco estado propio.
-`ui`: renderiza props preparadas y emite eventos.
La UI no debe contener reglas de dominio, fetch manual ni traducciones entre DTO y entidad. Los controllers no deben convertirse en servicios de dominio.
## 3. Módulos frontend
Cada módulo publica sus rutas y su cliente desde `modules/<module>/src/web`. Las features se organizan por caso de uso (`list`, `create`, `update`, `detail`) y comparten transporte, entidades y hooks mediante `shared` cuando existe reutilización real.
Las dependencias deben apuntar hacia contratos compartidos, no hacia páginas concretas. Un componente de dominio puede envolver una foundation visual si aporta defaults o vocabulario propios, pero no debe recrear el layout de página.
## 4. Routing y layouts
Las rutas declaran su shell en `handle.layout`:
-`auth`: login y recuperación, bajo `AuthLayout`.
-`app-sidebar`: dashboard, listados, settings y navegación general.
-`app-fullscreen`: tareas focalizadas de create/update/detail y Account cuando la ruta así lo declara.
`apps/web/src/routes/app-routes.tsx` agrupa las rutas por ese valor y las monta bajo el layout correspondiente. `protected` y `requireCompany` expresan guards independientes del shell. La elección debe seguir las rutas productivas del área; no se infiere únicamente por el nombre de la pantalla.
## 5. Shells de aplicación
```text
Application shell
├── AppSidebarLayout
│ ├── AppSidebar
│ ├── AppTopbar
│ └── AppMain
├── AppFullscreenLayout
│ └── AppMain
└── AuthLayout
```
-`AppSidebarLayout` proporciona navegación y topbar.
-`AppFullscreenLayout` ocupa el viewport para una tarea focalizada.
-`AuthLayout` centra las pantallas públicas de identidad.
-`AppMain` entrega el espacio disponible. No es propietario del scroll de una página.
Dentro de `AppMain`, una pantalla usa `RdxPageFrame`; el sistema visual y sus reglas se documentan en [UI system](./ui-system.md).
Regla: Las Pages no deben reconstruir estas responsabilidades con wrappers HTML locales. En Create/Update y Detail/Show, la composición canónica es RdxPageFrame → RdxPageContainer → RdxPageContent: errores, alertas, secciones semánticas y contenido funcional son hijos directos de RdxPageContent; los dialogs son hermanos del frame; RdxPanel se reserva para secciones semánticas reales.
El runtime actual se compone en `apps/web/src/app.tsx`:
```text
DataSourceProvider
└── IdentityAuthSessionProvider
└── router
```
El login usa `POST /identity/auth/login`. Tras autenticar:
1. persiste `accessToken` y `refreshToken`;
2. elimina cualquier empresa activa anterior;
3. obtiene la sesión con `GET /identity/auth/session`;
4. carga `GET /companies/available`;
5. resuelve la empresa activa y el destino autenticado.
Al restaurar una sesión, el provider valida el token, hidrata identidad y empresas y limpia ambos estados si la restauración falla. El frontend nuevo usa `@erp/identity/client`; no debe introducir dependencias nuevas sobre el runtime legacy de auth.
## 7. Selección de empresa
- Sin empresas: navega a `/no-companies`; no existe `activeCompanyId` y el logout permanece disponible.
- Una empresa: se selecciona automáticamente.
- Varias empresas: navega a `/company-selection` hasta que el usuario elige.
- Empresa persistida no disponible: vuelve a aplicar las tres reglas anteriores.
El switcher autenticado consume `availableCompanies`, `activeCompany` y `changeActiveCompany()` desde `useIdentityAuthSession()`. No obtiene tokens ni repite la consulta directamente.
## 8. Contexto tenant y `X-Company-Id`
Las requests tenant-scoped incluyen `X-Company-Id` cuando existe una empresa activa. No lo incluyen:
```text
POST /identity/auth/login
POST /identity/auth/refresh
POST /identity/auth/logout
GET /identity/auth/session
GET /companies/available
```
Los guards de compañía resuelven la navegación; los componentes visuales no deben inspeccionar headers HTTP ni decidir tenancy.
## 9. Refresh de Axios
Ante un `401` autenticado, el interceptor:
1. inicia `POST /identity/auth/refresh` si existe refresh token;
2. comparte una única `refreshPromise` entre requests concurrentes;
3. persiste los tokens renovados;
4. reintenta una sola vez la request original mediante `_retry`;
5. limpia sesión y navega a `/login` si el refresh falla.
Login, refresh, logout, session y companies available están excluidos del bucle de refresh y del header tenant. Una request tenant reintentada conserva el contexto de empresa.
## 10. Navegación y contexto
La navegación derivada de una operación pertenece al controller. Las páginas conectan callbacks y las vistas puras no importan React Router. El retorno desde editores debe reutilizar el mecanismo de `returnTo`/navegación existente en vez de reconstruir rutas localmente.
El estado remoto permanece en TanStack Query. No se duplica en estado local salvo estado efímero de presentación. Queries, invalidaciones y mutations viven en hooks compartidos del dominio.
## 11. Reglas de contribución arquitectónica
- Mantener TypeScript estricto y `import type` en cabecera.
- Naming y código en inglés; documentación y comentarios arquitectónicos en español.
- Preferir composición a frameworks CRUD o controllers genéricos.
- No introducir acceso a red en UI ni reglas de negocio en Pages.
- Mantener routing, sesión, tenant y sistema visual como responsabilidades separadas.
- Cambios de API visual pública deben sincronizar implementación, [UI system](./ui-system.md), UI Kit y tests.