dev8 mar 202511 min

Cómo estructurar un proyecto Nuxt grande sin perder el control

Cuando Nuxt crece, la clave no es añadir carpetas: es definir convenciones, límites de responsabilidad y flujos de calidad que el equipo pueda seguir sin pensar.

Por Alex Romero

Cómo estructurar un proyecto Nuxt grande sin perder el control

Nuxt.js es excelente para proyectos pequeños y medianos gracias a su convención sobre configuración. Pero cuando un proyecto crece —más páginas, más composables, más integraciones externas, más miembros en el equipo— las convenciones por defecto se quedan cortas. Sin una arquitectura deliberada, el código se acumula en `components/` y `composables/` sin estructura, las páginas empiezan a tener lógica de negocio, y cada nuevo desarrollador tarda días en entender cómo funciona el proyecto.

El principio fundamental: separación de responsabilidades

La mayoría de problemas de arquitectura en proyectos Nuxt grandes vienen de la misma causa: mezclar responsabilidades en la misma capa. Una página que hace una llamada a la API, transforma los datos, gestiona el estado local y renderiza el markup es imposible de mantener y testear.

La separación correcta sigue tres capas. La capa de presentación (components/ y pages/) solo se preocupa de cómo se ve y cómo interactúa el usuario. No tiene lógica de negocio —llama composables y renderiza lo que recibe. La capa de aplicación (composables/) contiene la lógica de negocio: gestión de estado, transformación de datos, validación. No llama APIs directamente —usa la capa de datos. La capa de datos (server/api/ o utils/api/) gestiona todas las comunicaciones externas: APIs REST, bases de datos, CMS. Devuelve datos normalizados que la capa de aplicación puede usar directamente.

  • Organiza por dominio, no por tipo de fichero: en lugar de components/forms/, components/cards/, components/modals/, usa components/users/, components/products/, components/checkout/. Cada carpeta de dominio contiene todos los componentes, composables y utils relacionados.
  • Composables orientados a casos de uso: useProductSearch() y useCartActions() en lugar de useApi() y useState(). El nombre debe describir qué hace, no cómo lo hace.
  • Centraliza clientes API: crea un fichero utils/api/client.ts que encapsule la configuración de $fetch (headers de autenticación, interceptores, gestión de errores). Nunca uses $fetch directamente desde un composable o componente.
  • Patrones de naming consistentes: usa PascalCase para componentes (UserCard.vue), camelCase para composables (useUserData.ts), kebab-case para páginas y rutas (/user-profile). Documenta las convenciones en un CONVENTIONS.md en el root.
  • Gestión de errores centralizada: crea un composable useError() que gestione todos los estados de error de manera uniforme. Evita que cada componente gestione sus propios errores de manera inconsistente.
  • Server routes para lógica sensible: toda la lógica que implica claves de API, acceso a bases de datos o transformaciones complejas debe ir a server/api/, no al cliente. Las Nuxt server routes se ejecutan en el servidor y no exponen lógica sensible al navegador.
  • Tests de regresión en puntos críticos: no hace falta testear todo, pero los composables con lógica de negocio importante (cálculos de precio, validación de formularios, transformación de datos) deben tener tests unitarios. Usa Vitest, que se integra perfectamente con Nuxt.
  • Documenta decisiones técnicas: usa ADRs (Architecture Decision Records) en una carpeta docs/decisions/. Cada decisión importante debe tener un fichero Markdown que explique el contexto, las alternativas consideradas y la decisión tomada.

Estructura recomendada para proyectos Nuxt de tamaño medio-grande

Una estructura que funciona bien para proyectos de 5-15 desarrolladores: `/app` para todo el código del cliente (pages, components, composables, organizados por dominio), `/server` para todas las API routes y middleware de servidor, `/shared` para tipos TypeScript, constantes y utils puras que se comparten entre cliente y servidor, y `/docs` para ADRs y documentación técnica.

La clave no es la carpeta —es la consistencia. Una estructura simple aplicada de manera consistente es infinitamente mejor que una arquitectura perfecta que el equipo no sigue. Define las convenciones, escríbelas, revísalas en code review y actualízalas cuando cambien las necesidades.

Una arquitectura simple y consistente reduce fricción, onboarding y errores en cada entrega. El mejor momento para definirla es cuando el proyecto empieza; el segundo mejor momento es ahora.