You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: DECISIONS.md
+11-11Lines changed: 11 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -46,34 +46,34 @@ Se usa **JSONB** para dos columnas clave:
46
46
47
47
---
48
48
49
-
## 3. Frontend: Arquitectura de Componentes por Features (autocontenidos)
49
+
## 3. Frontend: Vertical Slicing (Arquitectura por Features)
50
50
51
51
### Decisión
52
52
53
-
El frontend sigue una **arquitectura de componentes por feature**, donde cada feature (auth, dashboard, forms, builder, theme) es **autocontenido**: tiene su propio `index.ts` como API pública, y agrupa dentro de sí componentes, hooks, contexto y schemas. No hay carpeta global `components/hooks`; cada feature lleva sus hooks en una subcarpeta `hooks/` si los necesita (ej. `builder/hooks/`).
53
+
El frontend sigue **vertical slicing** (también conocido como **feature-based architecture** o **slice-by-feature**): cada **slice** o feature (auth, dashboard, forms, builder, theme) es una **unidad vertical autocontenida** con su propio `index.ts` como API pública, y agrupa dentro de sí componentes, hooks, contexto y schemas. No existe carpeta global `components/hooks`; cada feature lleva sus hooks en una subcarpeta `hooks/` si los necesita (ej. `builder/hooks/`).
54
54
55
-
Estructura actual:
55
+
Estructura actual (cada carpeta bajo `components/` es un slice vertical):
56
56
57
57
```
58
58
components/
59
59
auth/ → AuthForm, auth-form-schema (index exporta la API)
ui/ → Primitivos shadcn (sin index; import por archivo)
65
65
```
66
66
67
-
Las páginas importan desde el barrel del feature: `import { FormBuilder } from '@/components/builder'`, `import { AuthForm } from '@/components/auth'`. La convención completa está en el [README principal](./README.md#convenciones-de-componentes-frontend).
67
+
Las páginas importan desde el barrel del feature: `import { FormBuilder } from '@/components/builder'`, `import { AuthForm } from '@/components/auth'`. La convención completa está en el [README](./README.md#convenciones-de-componentes-vertical-slicing).
68
68
69
69
### Justificación
70
70
71
-
-**Colocación por feature**: Todo lo que pertenece a un flujo (login, builder, dashboard) vive junto. Cambios en el builder no dispersan archivos por `components/` y `hooks/`; todo está en `builder/`.
72
-
-**API pública clara**: El `index.ts` de cada feature define qué se expone al resto de la app. El resto son detalles internos del feature (layout, campos, hooks), lo que reduce acoplamiento y facilita refactors.
73
-
-**Hooks por feature, no globales**: Evitamos un cajón de sastre `src/hooks/` con lógica de un solo feature. Cada feature lleva sus hooks (use-form-builder, use-form-builder-dnd, use-form-builder-save en `builder/hooks/`). Solo hooks de utilidad realmente reutilizables (useDebounce, useMediaQuery) tendrían sentido en `src/hooks/` si se añaden.
74
-
-**Escalabilidad**: Si un feature crece (como el builder), se subdivide en subcarpetas (layout, fields, preview, hooks) con sus propios `index.ts`, sin contaminar la raíz de `components/`.
71
+
-**Vertical slicing**: Cada slice corta “en vertical” la capa de presentación: todo lo que pertenece a un flujo (login, builder, dashboard) vive junto. Cambios en el builder no dispersan archivos por `components/` y `hooks/`; todo está en `builder/`.
72
+
-**API pública por slice**: El `index.ts` de cada feature define qué se expone al resto de la app. El resto son detalles internos del slice (layout, campos, hooks), lo que reduce acoplamiento y facilita refactors.
73
+
-**Hooks por feature, no globales**: Evitamos un cajón de sastre `src/hooks/` con lógica de un solo feature. Cada slice lleva sus hooks (use-form-builder, use-form-builder-dnd, use-form-builder-save en `builder/hooks/`). Solo hooks de utilidad realmente reutilizables (useDebounce, useMediaQuery) tendrían sentido en `src/hooks/` si se añaden.
74
+
-**Escalabilidad**: Si un slice crece (como el builder), se subdivide en subcarpetas (layout, fields, preview, hooks) con sus propios `index.ts`, sin contaminar la raíz de `components/`.
75
75
-**Reutilización controlada**: `FieldRenderer` se usa en el preview del builder y en el formulario público; se exporta desde `@/components/forms` y el builder lo importa desde ahí, manteniendo una única fuente de verdad.
76
-
-**Composición**: Componentes pequeños y enfocados que se componen por feature; la app orquesta features, no decenas de componentes sueltos.
76
+
-**Composición**: Componentes pequeños y enfocados que se componen por feature; la app orquesta slices, no decenas de componentes sueltos.
### Convenciones de componentes (vertical slicing)
94
94
95
-
Cada **feature** (auth, dashboard, forms, builder, theme) es **autocontenido**: tiene su propio `index.ts` (API pública), y opcionalmente subcarpetas por responsabilidad. La app importa desde el barrel del feature, no por archivo.
95
+
El frontend usa **vertical slicing** (arquitectura por features): cada **slice** (auth, dashboard, forms, builder, theme) es una unidad vertical autocontenida con su propio `index.ts` (API pública) y, opcionalmente, subcarpetas por responsabilidad. La app importa desde el barrel del slice, no por archivo. Detalle en [DECISIONS.md §3](./DECISIONS.md#3-frontend-vertical-slicing-arquitectura-por-features).
|**API por feature**|`import { AuthForm } from '@/components/auth'`, `import { FormBuilder } from '@/components/builder'`, etc.|
100
-
|**ui/**| Sin index; imports directos: `@/components/ui/button`, `@/components/ui/card` (patrón shadcn). |
101
-
|**Subcarpetas**| Si un feature crece (ej. builder), se agrupa en `layout/`, `fields/`, `preview/`, `hooks/`, cada uno con su `index.ts`.|
102
-
|**Schemas y contexto**| Pertenecen al feature: `auth-form-schema.ts`, `form-builder-context.tsx`, `form-builder-schema.ts`.|
103
-
|**Hooks**| No hay `components/hooks` global. Cada feature lleva sus hooks dentro (ej. `builder/hooks/`). Solo hooks de utilidad reutilizables (useDebounce, useMediaQuery) irían en `src/hooks/` si se necesitan. |
104
-
|**Naming**| Archivos en kebab-case; componentes/hooks en PascalCase/camelCase. |
105
-
|**Tests**|`__tests__/` dentro del feature; imports relativos a archivos.|
|**API por slice**|`import { AuthForm } from '@/components/auth'`, `import { FormBuilder } from '@/components/builder'`, etc. |
100
+
|**ui/**| Sin index; imports directos: `@/components/ui/button`, `@/components/ui/card` (patrón shadcn). |
101
+
|**Subcarpetas**| Si un slice crece (ej. builder), se agrupa en `layout/`, `fields/`, `preview/`, `hooks/`, cada uno con su `index.ts`. |
102
+
|**Schemas y contexto**| Pertenecen al slice: `auth-form-schema.ts`, `form-builder-context.tsx`, `form-builder-schema.ts`. |
103
+
|**Hooks**| No hay `components/hooks` global. Cada slice lleva sus hooks dentro (ej. `builder/hooks/`). Hooks de utilidad reutilizables irían en `src/hooks/` si se necesitan. |
104
+
|**Naming**| Archivos en kebab-case; componentes/hooks en PascalCase/camelCase. |
105
+
|**Tests**|`__tests__/` dentro del slice; imports relativos a archivos. |
106
106
107
107
## Funcionalidades
108
108
@@ -125,7 +125,7 @@ Cada **feature** (auth, dashboard, forms, builder, theme) es **autocontenido**:
125
125
### Arquitectura
126
126
127
127
- ✅ Arquitectura Hexagonal (Clean Architecture) en backend
128
-
- ✅ Arquitectura de Componentes en frontend
128
+
- ✅ Arquitectura por componentes, estructura en vertical slicing (por features) en frontend
0 commit comments