Cómo organizo mis proyectos Next.js usando feature-based architecture
La estructura que uso en proyectos Next.js para mantener features más aisladas, escalables y fáciles de mantener.
Cuando un proyecto Next.js empieza a crecer, la carpeta components se convierte en un cajón de sastre. Hooks mezclados, utilidades que nadie sabe dónde quedaron, schemas perdidos. Al principio todo funciona bien, pero después de varias features mantener el contexto se vuelve difícil.
Yo pasé por eso varias veces hasta que empecé a organizar el código por feature.
El problema de las estructuras tradicionales
La mayoría empezamos con algo así:
src/
components/
hooks/
services/
utils/
Parece ordenado, pero una feature de autenticación termina repartida en cuatro carpetas distintas. El hook de login está en hooks, el formulario en components, los schemas de validación quién sabe dónde. Para entender una sola funcionalidad tienes que navegar por todo el proyecto.
Mientras más crece:
- más carpetas hay que abrir para entender una pantalla
- más contexto mental necesitas
- más miedo da refactorizar porque nunca sabes qué está tocando qué
La estructura que uso ahora
En vez de separar por tipo técnico, separo por dominio. En un proyecto real se ve así:
src/
features/
auth/
components/ → login-form, verify-code, passkeys-settings
hooks/ → queries, mutations
schemas/ → validación con zod
services/ → llamadas a la API
types/ → interfaces del dominio
utils/
cards/
components/ → create-card-dialog, card-links, stats, gallery
hooks/ → queries, mutations
services/ → cards.service.ts, card-stats.service.ts
schemas/ → validación de formularios
types/ → Card, CreateCardRequest, CardLink, etc.
templates/ → plantillas de diseño
utils/
Cada feature contiene todo lo que necesita para funcionar. Si quieres entender cómo funciona auth, entras a features/auth/ y tienes todo ahí. No tienes que andar saltando entre carpetas.
Esto hace que:
- escalar sea más fácil — agregas una carpeta, no diez archivos sueltos
- mover o eliminar features sea trivial — borras la carpeta y listo
- el ownership sea claro — sabes qué le pertenece a qué
- los tipos compartidos viajen por la feature, no por todo el proyecto
Trabajo actualmente en un dashboard administrativo con más de 15 features (auth, cards, companies, contacts, subscriptions, leads, etc.) y esta estructura es lo que permite que el proyecto siga siendo mantenible sin importar cuántas personas metan mano.
Qué evito hoy
Con el tiempo también fui aprendiendo qué no hacer:
- Barrel files (
index.ts) — parecen ordenados pero crean dependencias circulares y hacen que tu editor tarde en importar. Hoy prefiero imports directos. - Carpetas
utilsgigantes — si no puedes ponerle un nombre específico, probablemente esa función no debería existir. Una función llamadautils.tsno dice nada. - Lógica compleja dentro de componentes — si un componente tiene más de 100 líneas o maneja estado que no es de UI, lo muevo a un hook o a un servicio separado.
- Hooks demasiado grandes — un hook que mezcla fetching, estado local y side effects debería dividirse.
- Mezclar lógica de servidor y cliente — en Next.js App Router esto es clave. Lo que puede correr en el servidor, que corra en el servidor.
Stack con el que mejor funciona
Esta estructura la he usado tanto en proyectos con Next.js App Router como en proyectos con React + Vite + TanStack Router. En ambos casos el patrón es el mismo: las queries viven en features/X/hooks/queries.ts, los servicios en features/X/services/, y los componentes de UI compartidos se quedan en components/ui/ o components/shared/.
Funciona especialmente bien con:
- Next.js App Router o TanStack Router
- TypeScript (los tipos por feature ayudan un montón)
- TanStack Query (queries y mutations organizadas por feature)
- Zustand (stores chicos por feature)
- zod (schemas de validación cerca de los formularios)
- shadcn/ui (componentes atómicos en
components/ui/, componentes de feature enfeatures/) - Tailwind CSS
¿Cuándo vale la pena?
Para proyectos chicos, un par de páginas, un MVP rápido — probablemente no lo necesites. Pero cuando trabajas en:
- SaaS con múltiples módulos
- dashboards con varias secciones
- aplicaciones que sabes que van a vivir años
- proyectos donde van a meter mano varias personas
la diferencia se nota bastante. No es magia, no resuelve todos los problemas de arquitectura. Pero ayuda a mantener el código ordenado sin tener que pensar tanto en ello.
¿Tú cómo organizas tus proyectos? ¿Usas feature-based o prefieres otra estructura?