# Guía 4 — Patrones Arquitectónicos Aprobados ## Catálogo de patrones de desarrollo seguro y limpio para Next.js App Router > **Propósito:** Esta guía documenta los patrones de código oficiales del proyecto. Cualquier desvío de estos patrones debe estar debidamente motivado y registrado en Engram. --- ## 1. El Patrón Server-First (Server Components por defecto) En Next.js App Router, todos los componentes de la carpeta `app/` son **React Server Components** por defecto. Esto significa que se renderizan en el servidor, reduciendo el tamaño del bundle de JavaScript en el cliente y protegiendo accesos a base de datos o APIs downstream. ### Reglas del Patrón: 1. **Fetching Directo:** Las peticiones al backend Spring Boot se realizan directamente en la función asíncrona del componente, sin necesidad de usar `useEffect` o estados de React en el cliente. 2. **Seguridad Integrada:** Se verifica la sesión del usuario al inicio del renderizado usando `serverRequireAuth()`. ```typescript // app/dashboard/page.tsx import { serverRequireAuth } from '@/lib/auth/middleware'; import { fetchCuentasUsuario } from '@/standards/03-headers-contract'; export default async function DashboardPage() { // 1. Validar sesión en servidor const user = await serverRequireAuth(); // 2. Fetching asíncrono seguro const cuentas = await fetchCuentasUsuario(user.sessionReference); return (

Portal de Cuentas de {user.name}

); } ``` --- ## 2. El Patrón de Hidratación de Componentes del Cliente Cuando requerimos interactividad del usuario (clicks, formularios reactivos, modales dinámicos), declaramos un **Client Component** usando la directiva `'use client'` al principio del archivo. ### Reglas de Diseño: - **Área Limpia:** Mantén el Client Component lo más atómico y libre de fetching posible. Pasa los datos iniciales obtenidos en el Server Component como *Props*. - **Estado Global:** Si el componente altera el estado de la sesión, actualiza el store de Zustand. ```typescript // components/BotonTransferencia.tsx 'use client'; import { useState } from 'react'; import { logInfo } from '@/lib/logger/client-logger'; import { useAuthStore } from '@/lib/auth/client/useAuthStore'; interface BotonProps { cuentaOrigenId: string; } export default function BotonTransferencia({ cuentaOrigenId }: BotonProps) { const [loading, setLoading] = useState(false); const { user } = useAuthStore(); const handleTransfer = async () => { setLoading(true); logInfo('Acción de transferencia disparada', { cuentaOrigenId, userId: user?.id }); // Simular llamada de API local await new Promise((r) => setTimeout(r, 1000)); setLoading(false); }; return ( ); } ``` --- ## 3. Gobernanza de Estado Cliente con Zustand Evitamos el uso de React Context APIs redundantes o Redux pesado. El estado de la sesión cliente y configuraciones UI se centralizan en Zustand stores ubicados en `lib/auth/client/useAuthStore.ts`. ### Reglas del Patrón: 1. **Reactividad Fina:** Usa selectores en tus componentes para suscribirte solo a las propiedades requeridas (evita re-renders innecesarios). 2. **Acciones Claras:** Toda lógica que muta el estado debe encapsularse en las acciones del store. ```typescript // lib/auth/client/useAuthStore.ts import { create } from 'zustand'; interface User { id: string; name: string; } interface AuthState { user: User | null; isAuthenticated: boolean; login: (user: User) => void; logout: () => void; } export const useAuthStore = create((set) => ({ user: null, isAuthenticated: false, login: (user) => set({ user, isAuthenticated: true }), logout: () => set({ user: null, isAuthenticated: false }), })); ``` --- ## 4. El Patrón de Logging Proxy para el Cliente Como el cliente no tiene acceso al sistema de archivos local (`logs/app.log`), canalizamos todas las trazas de Client Components mediante el proxy seguro de Next.js `/api/logs`. * Ver `standards/01-log-tracing.md` para el flujo de llamadas y enrutamiento técnico de este patrón.