Fundamentos y Estructura
1. Regla sobre Principios Clave de Next.js​
Regla Principal​
Regla: El código generado o asistido por la IA debe diseñarse teniendo en cuenta y aprovechando los principios fundamentales de Next.js:
- Renderizado HÃbrido: Comprender y aplicar correctamente las estrategias de renderizado: Server-Side Rendering (SSR), Static Site Generation (SSG), Incremental Static Regeneration (ISR) y Client-Side Rendering (CSR) según las necesidades de cada página o componente. Por defecto, con App Router, los componentes son Server Components (renderizados en servidor).
- App Router: Utilizar la estructura de enrutamiento basada en directorios del App Router (
app/) para definir rutas, layouts, páginas, loading UI y error UI.- Server Components: Por defecto, los componentes dentro del App Router son Server Components. Deben usarse para acceder directamente a recursos del backend (bases de datos, APIs internas) y mantener la lógica sensible fuera del bundle del cliente. No deben usar estado (
useState), efectos (useEffect) ni interactividad del navegador.- Client Components: Marcar explÃcitamente con
'use client'al inicio del archivo aquellos componentes que necesiten interactividad, estado o efectos del lado del cliente. Minimizar el uso de Client Components y aislarlos tanto como sea posible.- Data Fetching: Utilizar las funciones y patrones recomendados por Next.js para la obtención de datos (ver Norma 6).
Contexto y Justificación​
Estos principios son la base de Next.js y permiten crear aplicaciones rápidas, eficientes y escalables. Aplicarlos correctamente asegura que se aprovechen las optimizaciones de rendimiento (renderizado en servidor, code splitting automático) y las caracterÃsticas de la arquitectura (Server/Client Components). Ignorarlos conduce a un rendimiento subóptimo y a un mal uso del framework.
Ejemplos y Contraejemplos​
- Correcto: Crear un componente en
app/dashboard/page.tsxque sea un Server Component por defecto y haga fetch de datos directamente. Crear un componente interactivoInteractiveButton.tsxencomponents/, marcarlo con'use client'y usaruseStatedentro de él. - Incorrecto: Intentar usar
useStateouseEffecten un Server Component (causará error). Marcar innecesariamente componentes con'use client'si no tienen interactividad. Realizar data fetching sensible directamente en un Client Component.
Cuándo Aplicar​
Siempre, al diseñar la estructura y los componentes de una aplicación Next.js con App Router.
Cuándo Evitar o Flexibilizar​
Estos principios son fundamentales. La elección especÃfica de la estrategia de renderizado o data fetching dependerá de los requisitos de la página, pero el modelo Server/Client Component es inherente al App Router.
2. Regla sobre Estructura del Proyecto (App Router)​
Regla Principal​
Regla: Todo proyecto Next.js generado o asistido por la IA debe seguir una estructura de directorios organizada y coherente, basada en el App Router:
.
├── app/ # Directorio principal de enrutamiento y UI
│ ├── layout.tsx # Layout raÃz obligatorio
│ ├── page.tsx # Página raÃz (homepage)
│ ├── globals.css # Estilos globales
│ ├── api/ # API Routes (backend)
│ │ └── [route]/route.ts
│ ├── (auth)/ # Grupo de rutas sin afectar URL (ej. para layouts especÃficos)
│ │ ├── login/page.tsx
│ │ └── layout.tsx
│ ├── [slug]/ # Ruta dinámica
│ │ └── page.tsx
│ ├── dashboard/ # Ruta estática
│ │ ├── layout.tsx # Layout especÃfico para dashboard
│ │ ├── page.tsx # Página principal de dashboard
│ │ ├── settings/page.tsx # Sub-ruta
│ │ └── loading.tsx # UI de carga para dashboard
│ └── error.tsx # UI de error para la raÃz (o segmentos especÃficos)
├── components/ # Componentes UI reutilizables (Server y Client)
│ ├── ui/ # Componentes UI genéricos (botones, inputs)
│ └── features/ # Componentes especÃficos de una funcionalidad
├── lib/ # Funciones helper, utils, lógica compartida (ej. DB client, auth utils)
├── hooks/ # Custom Hooks (marcados con 'use client')
├── styles/ # Otros archivos de estilo si no se usan globales o Tailwind
├── public/ # Archivos estáticos (imágenes, fuentes)
├── types/ # Definiciones de tipos TypeScript globales
├── middleware.ts # Middleware de Next.js
├── next.config.js # Configuración de Next.js
├── tsconfig.json # Configuración de TypeScript
└── .env.local # Variables de entorno localesLa IA debe colocar los archivos correspondientes (layouts, pages, loading, error, route handlers) dentro de la estructura de
app/. Los componentes reutilizables deben ir encomponents/, y la lógica/utilidades compartidas enlib/.
Contexto y Justificación​
El App Router introduce convenciones de archivos y directorios especÃficas (
page.tsx,layout.tsx,loading.tsx,error.tsx,route.ts) que Next.js utiliza para construir la interfaz de usuario y el enrutamiento. Seguir esta estructura es obligatorio para que el framework funcione correctamente y para mantener un proyecto organizado y predecible. La separación encomponents/ylib/mejora la reutilización y mantenibilidad.
Ejemplos y Contraejemplos​
- Correcto: Crear la página de perfil de usuario en
app/profile/page.tsx. Crear un componenteButton.tsxreutilizable encomponents/ui/Button.tsx. Crear una función para conectar a la base de datos enlib/db.ts. - Incorrecto: Poner la UI de una página directamente en
layout.tsx. Crear componentes UI dentro del directorioapp/. Poner lógica de conexión a BD dentro de un componente.
Cuándo Aplicar​
Siempre, al crear o modificar proyectos Next.js que utilicen el App Router (versión 13+).
Cuándo Evitar o Flexibilizar​
Esta estructura es la convención central del App Router y no debe flexibilizarse en sus aspectos fundamentales (uso de
app/,page.tsx,layout.tsx, etc.). La organización interna decomponents/olib/puede variar ligeramente, pero debe mantenerse coherente.
3. Regla sobre Convenciones de Naming y Exports​
Regla Principal​
Regla: Todo código generado o asistido por la IA debe seguir convenciones especÃficas de nomenclatura y exports para mantener consistencia y legibilidad.
- Directorios: Utilizar kebab-case para nombres de directorios (ej.
components/auth-form,app/user-profile,lib/database-utils).- Archivos de Componentes: Utilizar PascalCase para archivos de componentes React (ej.
Button.tsx,UserProfile.tsx,AuthForm.tsx).- Named Exports: Preferir named exports sobre default exports para componentes y funciones. Usar
export function ComponentName()en lugar deexport default function ComponentName().- Consistencia: Mantener estas convenciones de forma consistente en todo el proyecto para facilitar la navegación y el mantenimiento.
Contexto y Justificación​
Las convenciones de naming consistentes mejoran la legibilidad del código y facilitan la navegación en proyectos grandes. El kebab-case para directorios es más legible en URLs y sistemas de archivos, mientras que PascalCase para componentes sigue las convenciones de React. Los named exports mejoran la refactorización automática, el tree-shaking y la experiencia de autocompletado en IDEs.
Ejemplos y Contraejemplos​
- Correcto:
// Estructura de directorios
components/
auth-form/
AuthForm.tsx
auth-form.module.css
user-profile/
UserProfile.tsx
// Named exports
// components/ui/Button.tsx
export function Button({ children, onClick }: ButtonProps) {
return <button onClick={onClick}>{children}</button>;
}
export function PrimaryButton(props: ButtonProps) {
return <Button {...props} className="primary" />;
}
// Importación
import { Button, PrimaryButton } from '@/components/ui/Button'; - Incorrecto:
// Directorios con PascalCase o camelCase
components/AuthForm/ // DeberÃa ser auth-form
components/userProfile/ // DeberÃa ser user-profile
// Default exports
export default function Button() { /* ... */ } // Usar named export
// Archivos con kebab-case
auth-form.tsx // DeberÃa ser AuthForm.tsx para componentes
Cuándo Aplicar​
Siempre, al crear nuevos archivos, directorios y componentes en el proyecto Next.js.
Cuándo Evitar o Flexibilizar​
Las convenciones de archivos especiales de Next.js (
page.tsx,layout.tsx,loading.tsx, etc.) deben mantenerse como están definidas por el framework. Para archivos de configuración o utilidades que no sean componentes React, se pueden usar otras convenciones apropiadas (ej.database.config.ts).
4. Regla sobre Uso de TypeScript​
Regla Principal​
Regla: Todo proyecto Next.js generado o asistido por la IA debe utilizar TypeScript de forma estricta y eficaz.
- Tipado Estricto: Habilitar y respetar las opciones estrictas de TypeScript en
tsconfig.json("strict": trueo equivalentes individuales comonoImplicitAny,strictNullChecks, etc.).- Props de Componentes: Definir interfaces (
interface) o tipos (type) explÃcitos para las props de todos los componentes React (Server y Client Components).- Tipos de Datos: Tipar explÃcitamente los datos obtenidos de APIs, bases de datos o cualquier fuente externa. Crear tipos o interfaces en
types/o localmente si son especÃficos.- Funciones y Hooks: Tipar los parámetros y valores de retorno de funciones y custom hooks.
- Eventos: Utilizar los tipos de eventos de React (
React.ChangeEvent<HTMLInputElement>,React.MouseEvent<HTMLButtonElement>, etc.) para los manejadores de eventos en Client Components.- Evitar
any: Prohibir el uso explÃcito o implÃcito deany. Utilizarunknownjunto con type narrowing (comprobación de tipos) cuando el tipo no sea conocido de antemano.
Contexto y Justificación​
TypeScript mejora drásticamente la mantenibilidad, refactorización y detección temprana de errores en aplicaciones grandes como las construidas con Next.js. El tipado estricto asegura que se aprovechen al máximo los beneficios de TypeScript. Definir tipos claros para props, datos y funciones mejora la legibilidad y reduce errores en tiempo de ejecución.
Ejemplos y Contraejemplos​
- Correcto:
// --- components/ui/UserProfile.tsx ---
interface UserProfileProps {
userId: string;
name: string | null;
email: string;
isActive: boolean;
onUpdate?: (newName: string) => void; // Prop opcional de función
}
export function UserProfile({ userId, name, email, isActive, onUpdate }: UserProfileProps) {
// ... render JSX ...
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
// ...
};
return (
<div>
{/* ... */}
{onUpdate && <button onClick={handleClick}>Actualizar</button>}
</div>
);
}
// --- lib/utils.ts ---
export function formatCurrency(value: number | null | undefined): string {
if (value === null || value === undefined) {
return 'N/A';
}
return value.toLocaleString('es-ES', { style: 'currency', currency: 'EUR' });
} - Incorrecto: Props de componentes sin tipar (
function MyComponent(props)) . Usaranypara datos de API (const data: any = await res.json()). No tipar parámetros de funciones (function process(data)). Usar tipos genéricos de evento (onClick={(e) => ...}). No habilitarstrictNullChecks.
Cuándo Aplicar​
Siempre, en todo el código TypeScript de la aplicación Next.js.
Cuándo Evitar o Flexibilizar​
Nunca se debe flexibilizar el uso estricto de TypeScript. El uso de
anyestá prohibido salvo en circunstancias excepcionales y muy justificadas (ej. integración con librerÃas JS legacy sin tipos) y debe encapsularse.
5. Regla sobre Linters y Formatters (ESLint, Prettier)​
Regla Principal​
Regla: Todo proyecto Next.js debe configurar y utilizar ESLint y Prettier para mantener la calidad y consistencia del código.
- ESLint: Configurar ESLint con el plugin
eslint-config-nextque incluye reglas especÃficas para Next.js, React y accesibilidad (jsx-a11y). Habilitar reglas recomendadas de TypeScript (@typescript-eslint/recommended).- Prettier: Configurar Prettier para formatear automáticamente el código según un estilo consistente. Integrarlo con ESLint (
eslint-config-prettier) para evitar conflictos de reglas.- Integración: Ejecutar ESLint y Prettier automáticamente en el flujo de trabajo, preferentemente usando Git Hooks (con
huskyylint-staged) para asegurar que el código commiteado cumpla las reglas y esté formateado.- Resolución de Errores: La IA debe generar código que cumpla las reglas de ESLint configuradas. Si se detectan errores de linter, la IA debe intentar corregirlos.
Contexto y Justificación​
ESLint ayuda a detectar errores de código, potenciales bugs y malas prácticas especÃficas de React/Next.js. Prettier asegura un estilo de código uniforme en todo el proyecto, mejorando la legibilidad y reduciendo discusiones sobre formato. Su uso conjunto y automatizado es esencial para mantener la calidad en equipos y proyectos grandes.
Ejemplos y Contraejemplos​
- Correcto (Configuración conceptual):
package.jsoncon dependencias:eslint,eslint-config-next,@typescript-eslint/eslint-plugin,prettier,eslint-config-prettier,husky,lint-staged.- Archivo
.eslintrc.jsonextendiendo["next/core-web-vitals", "plugin:@typescript-eslint/recommended", "prettier"]. - Archivo
.prettierrc.jso similar con la configuración de formato. - Configuración de
lint-stagedenpackage.jsonpara ejecutareslint --fixyprettier --writeen archivos stageados. - Scripts en
package.json:"lint": "eslint .","format": "prettier --write .".
- Incorrecto: No tener ESLint o Prettier configurados. Ignorar errores de ESLint. Código con formato inconsistente. Falta de integración con Git Hooks.
Cuándo Aplicar​
Siempre, desde el inicio del proyecto Next.js.
Cuándo Evitar o Flexibilizar​
Nunca. La configuración base con
eslint-config-nexty Prettier es fundamental. Se pueden añadir o ajustar reglas especÃficas de ESLint según las necesidades del proyecto, pero la base debe existir.