Lista de Verificación de Decisiones de Arquitectura en React
Una lista de verificación de las decisiones arquitectónicas que moldean cada proyecto de React, ordenadas de lo fundamental a lo específico. Úsala al iniciar una nueva app, auditar una existente o justificar una elección de stack a un equipo.
Cómo Usar Esta Lista de Verificación
- Recorre la lista de arriba a abajo - las decisiones anteriores limitan las posteriores.
- Para cada fila, escribe tu elección y tu justificación - las elecciones sin justificación derivan.
- Marca explícitamente cualquier fila que omitas como "N/A" con una razón, para que el próximo ingeniero sepa que la consideraste.
- Revisita la lista en cada hito importante (MVP, v1, pico de escalado) - la respuesta correcta cambia a medida que el proyecto crece.
Decisiones de Arquitectura
-
Framework: Next.js vs Vite vs Remix vs TanStack Start
- Next.js: elige para SSR/SSG, apps críticas para SEO, o cuando quieras una configuración full-stack completa con App Router y React Server Components.
- Vite: elige para SPAs puras, herramientas internas o dashboards donde el HMR rápido en desarrollo importa más que SSR.
- Remix: elige cuando quieras enrutamiento anidado basado en fundamentos web, loaders/actions y mejora progresiva integrados.
- TanStack Start: elige cuando quieras enrutamiento type-safe con SSR pero más flexibilidad que Next.js.
-
Estrategia de Renderizado: SSR vs SSG vs CSR vs ISR
- SSR: páginas públicas con personalización por solicitud o datos que cambian frecuentemente.
- SSG: sitios de marketing, documentación o blogs donde el contenido rara vez cambia y quieres hosting CDN económico.
- CSR: shells de apps autenticadas detrás de un login donde SEO no importa.
- ISR: sitios híbridos con contenido mayormente estático pero revalidación ocasional en segundo plano (por ejemplo, catálogos de ecommerce).
-
Lenguaje: TypeScript vs JavaScript
- TypeScript: predeterminado para cualquier equipo o app no trivial; detecta bugs en tiempo de compilación y hace las refactorisaciones más seguras.
- JavaScript: solo para prototipos diminutos, demostraciones desechables, o cuando los colaboradores carecen estrictamente de familiaridad con TS.
-
Gestor de Paquetes: pnpm vs npm vs yarn vs bun
- pnpm: monorepos y proyectos sensibles al espacio en disco y velocidad de instalación, gracias a su almacén direccionable por contenido.
- npm: cero configuración, se envía con Node, máxima compatibilidad con tutoriales y ejemplos de CI.
- yarn: configuraciones existentes de yarn berry (PnP) o equipos ya comprometidos con yarn workspaces.
- bun: proyectos greenfield priorizando velocidad bruta de instalación/ejecución y dispuestos a aceptar un ecosistema más joven.
-
Estructura del Repositorio: Monorepo (Turborepo/Nx) vs Polyrepo
- Monorepo: múltiples apps compartiendo componentes UI, tipos o utils (web + mobile + admin dashboard).
- Polyrepo: app individual, equipo pequeño, o límites de propiedad estrictos entre servicios.
-
Enrutamiento: Basado en archivos vs React Router vs TanStack Router
- Basado en archivos (Next/TanStack): convención sobre configuración; las rutas mapean al filesystem, excelente para estandarización.
- React Router: SPAs donde quieres control programático completo y una API madura y familiar.
- TanStack Router: necesitas rutas completamente type-safe con validación de parámetros de búsqueda y fetching de datos basado en loaders.
-
Gestión de Estado del Cliente: Zustand vs Redux Toolkit vs Jotai vs Context API
- Zustand: boilerplate mínimo, buena opción predeterminada para la mayoría de apps que necesitan estado compartido.
- Redux Toolkit: apps grandes con máquinas de estado complejas, depuración de viaje en el tiempo, o experiencia previa con Redux.
- Jotai: estado que es naturalmente atómico y derivado - bueno para formularios complejos o estado similar a grafos.
- Context API: valores verdaderamente globales y raramente cambiantes como tema o usuario auth; evita para cualquier cosa que se actualice frecuentemente.
-
Estado del Servidor / Fetching de Datos: TanStack Query vs SWR vs RTK Query vs Apollo
- TanStack Query: predeterminado para REST - caching, mutaciones, devtools, agnóstico del framework.
- SWR: API más simple, ligero, integración estrecha si estás en el ecosistema de Vercel.
- RTK Query: ya usas Redux Toolkit y quieres fetching de datos en el mismo store.
- Apollo: GraphQL con caching normalizado, actualizaciones optimistas y suscripciones.
-
Enfoque de Styling: Tailwind vs CSS Modules vs styled-components vs vanilla-extract
- Tailwind: iteración rápida, tokens de diseño consistentes, se complementa perfecto con shadcn/ui.
- CSS Modules: quieres CSS plano con alcance, cero runtime y ningún DSL nuevo que aprender.
- styled-components: theming dinámico y CSS-in-JS colocado, aceptando el costo de runtime.
- vanilla-extract: CSS-in-TS type-safe y cero runtime para autores de design systems.
-
Librería de Componentes: shadcn/ui vs MUI vs Chakra vs Radix + custom
- shadcn/ui: quieres componentes copiados y completamente poseídos construidos en Radix + Tailwind.
- MUI: apps empresariales necesitando componentes integrales estilo Material out of the box.
- Chakra: componentes accesibles y temables con una API amigable basada en props.
- Radix + custom: quieres primitivos headless accesibles y una identidad visual completamente personalizada.
-
Formularios: React Hook Form vs TanStack Form vs Formik
- React Hook Form: elección predeterminada - performante, no controlado, se complementa bien con resolvers Zod.
- TanStack Form: profundamente type-safe con validación asincrónica de primera clase y arrays de campos.
- Formik: solo para proyectos legacy ya usándolo; generalmente no recomendado para trabajo nuevo.
-
Validación de Esquema: Zod vs Valibot vs Yup
- Zod: estándar de facto; excelente inferencia de TS, integración amplia del ecosistema (RHF, tRPC, etc.).
- Valibot: apps sensibles al tamaño del bundle - modular y tree-shakable con ergonomía similar a Zod.
- Yup: proyectos existentes con Formik o si prefieres su estilo de validación asincrónica-first.
-
Capa de API: REST vs GraphQL vs tRPC
- REST: APIs públicas, máxima compatibilidad de cliente, o necesidades CRUD simples.
- GraphQL: múltiples clientes con necesidades de datos divergentes y consultas anidadas complejas.
- tRPC: proyecto full-stack TypeScript donde la API solo es consumida por tus propios clientes.
-
Autenticación: Auth.js vs Clerk vs Auth0 vs custom
- Auth.js (NextAuth): open-source, auto-hospedado, muchos proveedores OAuth out of the box para Next.js.
- Clerk: UI plug-and-play, dashboards de gestión de usuarios, y estás feliz pagando por velocidad.
- Auth0: SSO empresarial, SAML y requisitos de cumplimiento normativo.
- Custom: flujos de auth inusuales o requisitos estrictos de residencia de datos que excluyen terceros.
-
Testing Unitario/Integración: Vitest vs Jest
- Vitest: proyectos basados en Vite y cualquiera queriendo un runner más rápido y ESM-nativo con API compatible con Jest.
- Jest: suites de pruebas grandes existentes, Next.js sin Vite, o herramientas que asumen específicamente Jest.
-
Testing E2E: Playwright vs Cypress
- Playwright: cobertura multi-navegador (WebKit/Firefox), paralelismo, y DX moderno - recomendación predeterminada.
- Cypress: depuración pesada de viaje en el tiempo y una interfaz más rica para diagnóstico de pruebas inestables.
-
Linting y Formateo: ESLint + Prettier vs Biome
- ESLint + Prettier: ecosistema maduro con plugins para cada framework y regla imaginable.
- Biome: proyectos greenfield queriendo una única herramienta rápida basada en Rust para linting y formateo.
-
Estructura de Carpetas: Basada en características vs Basada en tipos vs Atomic Design
- Basada en características: coloca todo el código por característica de dominio - escala mejor a medida que las apps crecen.
- Basada en tipos (components/, hooks/, etc.): bien para apps pequeñas pero difícil pasado ~20 características.
- Atomic Design: apps pesadas en design system donde los primitivos de UI reutilizables son la preocupación principal.
-
Estrategia de Code Splitting: Splitting a nivel de ruta vs Lazy loading a nivel de componente
- Splitting a nivel de ruta: predeterminado; divide en límites de página para las mejores ganancias de TTI con esfuerzo mínimo.
- Lazy loading a nivel de componente: widgets específicos pesados (gráficos, editores ricos, mapas) que se renderizan condicionalmente.
-
Monitoreo de Errores: Sentry vs LogRocket vs Datadog
- Sentry: rastreo de errores de mejor-en-clase con source maps, releases y monitoreo de performance.
- LogRocket: necesitas session replay junto con errores para depurar problemas de UX.
- Datadog: ya estás estandarizado en él para observabilidad de backend y quieres un único panel.
-
Analytics: PostHog vs Google Analytics vs Plausible vs Mixpanel
- PostHog: product analytics con feature flags, session replay y opción de auto-hospedaje.
- Google Analytics: gratis, ubicuo, y suficiente para métricas de marketing/tráfico.
- Plausible: ligero, privacy-first, sin cookies - bueno para cumplimiento de UE.
- Mixpanel: análisis de funnel y cohorte para equipos de producto que viven en datos de eventos.
-
CI/CD: GitHub Actions vs GitLab CI vs CircleCI
- GitHub Actions: predeterminado si tu repo está en GitHub - integración profunda y enorme marketplace.
- GitLab CI: tu fuente está en GitLab; integración estrecha con Auto DevOps.
- CircleCI: equipos queriendo primitivos de paralelismo potentes y caching maduro out of the box.
-
Hosting / Despliegue: Vercel vs Netlify vs AWS vs Cloudflare Pages
- Vercel: apps Next.js - soporte first-party, runtime edge, despliegues preview.
- Netlify: sitios Jamstack, funciones serverless, y tier libre generoso.
- AWS: necesitas control completo, VPCs personalizadas, o ya vives en AWS.
- Cloudflare Pages: apps edge-first, precios agresivos, integración estrecha con Workers.
-
Gestión de Variables de Entorno: Archivos .env vs Doppler vs AWS Secrets Manager
- Archivos .env: proyectos simples con pocos secretos y devs de confianza.
- Doppler: equipos necesitando sincronización compartida y auditada de secretos entre envs sin complejidad de AWS.
- AWS Secrets Manager: stacks nativos de AWS con rotación, políticas de IAM y necesidades de cumplimiento.
-
Internacionalización (i18n): next-intl vs react-i18next vs Lingui
- next-intl: Next.js App Router con soporte RSC de primera clase.
- react-i18next: maduro, agnóstico del framework, enorme ecosistema de plugins.
- Lingui: extracción de mensajes en tiempo de compilación y runtime más pequeño, basado en ICU.
-
Animación: Framer Motion vs React Spring vs CSS/Tailwind
- Framer Motion: animaciones declarativas, gestos y layout animations con código mínimo.
- React Spring: animaciones basadas en física y control fino.
- CSS/Tailwind: transiciones simples y efectos hover - costo de runtime JS nulo.
-
Sistema de Iconos: Lucide vs Heroicons vs custom SVG sprites
- Lucide: conjunto de iconos moderno más grande con componentes React tree-shakables.
- Heroicons: limpio, alineado con Tailwind, se complementa bien con shadcn/ui.
- Custom SVG sprites: iconografía específica de marca o presupuestos estrictos de tamaño de bundle.
-
Manejo de Fecha/Hora: date-fns vs Day.js vs Luxon vs Temporal
- date-fns: utilidades funcionales tree-shakables; elección predeterminada para la mayoría de apps.
- Day.js: API similar a Moment en un bundle diminuto - bueno para migraciones rápidas desde Moment.
- Luxon: necesidades pesadas de zona horaria y calendarios, construido en Intl.
- Temporal (polyfill): quieres el estándar futuro hoy y estás bien enviando el polyfill.
-
Documentación de Componentes: Storybook vs Ladle vs ninguno
- Storybook: design system o librería de componentes compartida consumida por múltiples equipos.
- Ladle: basado en Vite, alternativa más rápida para catálogos de componentes más simples.
- Ninguno: productos en etapa temprana donde los componentes cambian diariamente y la documentación se pudre más rápido de lo que ayuda.
-
Optimización de Imágenes: next/image vs Cloudinary vs custom (Sharp + CDN)
- next/image: proyectos Next.js - redimensionamiento automático, lazy loading y negociación de formato.
- Cloudinary: necesitas transformaciones al vuelo, entrega de CDN, y trabajas en frameworks sin Next.
- Custom (Sharp + CDN): control completo, sensible al costo a escala, o pipelines de imagen altamente específicos.
Aplicando la Lista de Verificación en Orden
- Nivel foundacional (1–5): framework, renderizado, lenguaje, gestor de paquetes, estructura del repo. Costoso de revertir - acértalos o acepta el costo de una futura migración.
- Nivel de stack central (6–14): enrutamiento, estado, datos, styling, UI, formularios, validación, API, auth. Cambiable, pero cada intercambio cuesta semanas.
- Nivel de calidad (15–19): testing, linting, estructura de carpetas, code splitting. Fácil de agregar después - pero barato de configurar ahora y doloroso de retroceder.
- Nivel de ops (20–24): monitoreo, analytics, CI/CD, hosting, secretos. Requerido antes del tráfico de producción; no lances sin ellos.
- Nivel de pulido (25–30): i18n, animación, iconos, fechas, documentación de componentes, imágenes. Agrega cuando el producto lo demanda - adopción prematura hincha el bundle.
Gotchas
- Elegir herramientas aisladamente - Elegir "la mejor librería de estado" antes de conocer el framework o estrategia de renderizado lleva a desajustes (por ejemplo, Redux con RSC). Fix: Recorre la lista de arriba a abajo; las decisiones anteriores limitan las posteriores.
- Copiar stacks de FAANG para un equipo de 5 personas - Las herramientas empresariales (Nx, Auth0, Datadog) agregan complejidad y costo sin los problemas que resuelven. Fix: Adapta las herramientas al tamaño del equipo y tráfico - actualiza cuando sientas el dolor.
- Sin justificación escrita - Las elecciones de stack sin justificación se cuestionan cada vez que se une un nuevo hire y derivan silenciosamente. Fix: Escribe un "por qué" de una oración por decisión en un ADR (architecture decision record) confirmado en el repo.
- Bloquearse en la capa de API demasiado pronto - Elegir GraphQL o tRPC antes de conocer tu forma de cliente a menudo causa una reescritura dolorosa en v2. Fix: Comienza con REST en la primera iteración; migra solo una vez que los patrones de fetching de datos sean claros.
- Agregar observabilidad al final - Sentry, analytics y feature flags instalados post-lanzamiento pierden la primera ronda de bugs de usuarios reales. Fix: Incluye monitoreo de errores y analytics en el primer despliegue a producción, incluso con un tier libre.
- Cambios repetidos de decisión de styling - Mezclar Tailwind, CSS Modules y styled-components en un repo destruye tamaño de bundle y consistencia. Fix: Elige un enfoque de styling principal y refuérzalo mediante lint rules.
- Saltar TypeScript "para moverse rápido" - Los prototipos de JS que tienen éxito se convierten en migraciones de TS bajo presión de plazo. Fix: Comienza con TypeScript incluso en prototipos; modo strict puede venir después.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| ADRs (Architecture Decision Records) | Quieres un rastro de auditoría completo con contexto, consecuencias y notas de supersección. | Solo necesitas una lista de verificación rápida para un equipo pequeño. |
| RFC / Documentos de Diseño Técnico | Las decisiones necesitan revisión entre equipos antes del compromiso. | La decisión está limitada a un equipo y un repo. |
| Generadores de selección de stack (por ejemplo, create-t3-app) | Quieres un stack preset "lo suficientemente bueno" y no necesitas justificar cada elección. | Tienes restricciones que el generador no conoce (cumplimiento, infra existente). |
| AWS Well-Architected Framework | Las decisiones de infra en la nube dominan tu arquitectura. | El producto es principalmente un SPA frontend con backend mínimo. |
FAQs
¿Por qué debería recorrer la lista de arriba a abajo en lugar de seleccionar decisiones?
- Las decisiones foundacionales (framework, renderizado, lenguaje) limitan todas las elecciones posteriores.
- Elegir una librería de estado antes de un framework lleva a desajustes como Redux con RSC.
- El orden refleja el costo de reversibilidad - las filas 1–5 son caras de deshacer; las filas 25–30 son baratas.
¿Cuándo debería elegir Next.js sobre Vite?
- SSR/SSG o páginas críticas para SEO: Next.js.
- SPA autenticada pura o dashboard interno sin SEO: Vite.
- Next.js agrega App Router + React Server Components out of the box; Vite te da el HMR más rápido en desarrollo y nada más.
¿Cuál es la diferencia entre SSR, SSG, CSR e ISR en una oración cada una?
- SSR - HTML renderizado por solicitud en el servidor.
- SSG - HTML construido una vez en tiempo de despliegue y servido desde un CDN.
- CSR - el navegador renderiza todo desde un bundle de JS, el servidor envía un shell vacío.
- ISR - SSG con revalidación en segundo plano en un temporizador o disparador.
¿Realmente vale la pena TypeScript para prototipos pequeños?
- Sí, comienza con TypeScript incluso en prototipos - modo strict puede venir después.
- Los prototipos de JS que tienen éxito se convierten en migraciones de TS bajo presión de plazo.
- Las únicas excepciones honestas son demostraciones desechables o colaboradores que carecen estrictamente de familiaridad con TS.
¿Cuándo un monorepo se vuelve rentable sobre un polyrepo?
- Monorepo vale la pena cuando tienes múltiples apps compartiendo UI, tipos o utils (web + mobile + admin).
- Polyrepo gana para una app individual, equipo pequeño, o límites de propiedad de servicio estrictos.
- Turborepo/Nx agregan caching y orquestación de tareas - no los adoptes hasta que sientas el dolor de herramientas duplicadas.
¿Cuál librería de estado del cliente debería elegir por defecto?
- Zustand - boilerplate mínimo, buena opción predeterminada para la mayoría de apps.
- Redux Toolkit - apps grandes con máquinas de estado complejas o experiencia previa con Redux.
- Jotai - estado atómico/derivado para formularios o estado similar a grafos.
- Context API - valores verdaderamente globales y raramente cambiantes como tema o usuario auth solamente.
¿Por qué es TanStack Query el predeterminado para estado del servidor?
- Caching, mutaciones, devtools y agnóstico del framework - funciona con cualquier API REST.
- SWR es más simple pero menos feature-rich; úsalo si ya estás en el ecosistema de Vercel.
- RTK Query solo tiene sentido si ya estás en Redux Toolkit.
- Apollo es para GraphQL con caching normalizado.
¿Cómo decido entre REST, GraphQL y tRPC?
- REST - APIs públicas, máxima compatibilidad, CRUD simple.
- GraphQL - múltiples clientes con necesidades de datos divergentes y consultas anidadas.
- tRPC - full-stack TypeScript donde la API solo es consumida por tus propios clientes.
- Comenzar con REST y migrar después es casi siempre más barato que elegir GraphQL demasiado pronto.
¿Cuál enfoque de styling se complementa mejor con shadcn/ui?
- Tailwind - shadcn/ui está construido en Tailwind + Radix; ese es el emparejamiento canónico.
- CSS Modules y vanilla-extract funcionan pero sacrifican los beneficios de tokens de diseño.
- Nunca mezcles Tailwind con styled-components en un repo - el tamaño del bundle y la consistencia sufren.
¿Cuál es el gotcha con elegir Context API para estado compartido?
- Context re-renderiza cada consumidor en cada cambio de valor - bien para valores estáticos, brutal para los que se actualizan frecuentemente.
- Úsalo para tema, usuario auth, locale - no para contadores, estado de formulario, o datos de servidor.
- Alcanza Zustand o Jotai en el momento en que el valor se actualiza más de una vez por interacción del usuario.
¿Cuándo debería agregar Sentry, analytics y feature flags?
- En el primer despliegue a producción - retroceder observabilidad pierde la primera ronda de bugs de usuarios reales.
- Los tiers libre de Sentry y PostHog cubren la mayoría de apps pequeñas.
- Inclúyelos en tu pipeline de CI/CD inicial para que release tagging y source maps simplemente funcionen.
¿Por qué es arriesgado elegir la capa de API demasiado pronto?
- GraphQL y tRPC ambos codifican suposiciones sobre la forma del cliente que a menudo resultan estar equivocadas en v2.
- Un MVP REST-first te da espacio para ver patrones de fetching de datos reales antes de comprometerte.
- Migra una vez - no dos - difiriendo la decisión hasta que la forma del cliente se estabilice.
¿Necesito Storybook en el día uno?
- No - salta la documentación de componentes hasta que tengas un design system consumido por múltiples equipos.
- Los productos en etapa temprana cambian componentes diariamente; la documentación se pudre más rápido de lo que ayuda.
- Ladle es una alternativa más rápida basada en Vite cuando eventualmente quieras documentación estilo catálogo.
¿Cuál es el signo más rápido de que sobre-ingenierizaste el stack?
- Estás ejecutando Nx, Auth0, Datadog y una puerta GraphQL para un equipo de 5 personas.
- Las herramientas empresariales agregan costo y complejidad sin los problemas que resuelven para equipos pequeños.
- Adapta las herramientas al tamaño del equipo y tráfico - actualiza cuando el dolor se presente, no antes.
¿Cuál es lo primero que debería hacer después de terminar esta lista de verificación?
- Confirma tus respuestas como un ADR (architecture decision record) en el repo.
- Incluye justificación y una fecha de revisita para cada decisión.
- Comparte con el equipo y revisita en cada hito importante (MVP, v1, pico de escalado).
Relacionado
- React Fundamentals Best Practices - Reglas a nivel de componente que siguen de las elecciones de stack aquí.
- Component Decision Workflow - Cómo decidir dónde vive un componente y qué posee.
- Next.js Setup - Pasos concretos de configuración una vez que Next.js se elige.
- TypeScript + React - Patrones de tipo para cualquiera de las elecciones de stack anteriores.