# Regla: Estilo de Código — Next.js

Aplica a todo código Next.js del proyecto. El App Router introduce un modelo
mental distinto al Pages Router: los componentes son Server Components por defecto
y el cliente es la excepción. Estas reglas establecen cuándo cruzar esa frontera
y cómo mantener el código legible y navegable.

---

## ESLint + eslint-config-next (obligatorio)

- `eslint-config-next` se instala con `create-next-app` y es obligatorio.
- Ningún PR se aprueba con warnings de ESLint activos.
- Ejecutar antes de cada commit:
  ```bash
  next lint
  ```
- CI falla si `next lint` reporta errores o warnings.
- Reglas adicionales recomendadas en `.eslintrc.json`:
  ```json
  {
    "extends": ["next/core-web-vitals"],
    "rules": {
      "no-console": "error",
      "prefer-const": "error"
    }
  }
  ```

---

## Prettier como formateador

- Prettier define el estilo de formato. No se debate sobre indentado o comillas.
- Configuración mínima en `.prettierrc`:
  ```json
  {
    "semi": false,
    "singleQuote": true,
    "tabWidth": 2,
    "trailingComma": "all",
    "printWidth": 100
  }
  ```
- Ejecutar `prettier --check .` en CI. Bloquear merge si hay diferencias.
- Integrar con el editor: guardar debe formatear automáticamente.

---

## App Router como patrón principal

- Todo proyecto nuevo usa **App Router** (`app/`). No usar Pages Router (`pages/`)
  para proyectos iniciados con Next.js 13.4+.
- La migración de Pages a App Router no se hace parcialmente en un PR —
  documentar como ADR si se decide migrar.

---

## "use client" solo cuando es estrictamente necesario

- Los componentes son **Server Components por defecto**. No agregar `"use client"`
  por costumbre o para evitar errores que aún no ocurrieron.

**Cuándo SÍ usar `"use client"`:**
- El componente usa `useState`, `useReducer`, `useContext`
- El componente usa `useEffect`, `useLayoutEffect`
- El componente usa event handlers (`onClick`, `onChange`, `onSubmit`)
- El componente usa APIs del browser (`window`, `document`, `navigator`)
- El componente usa librerías que solo funcionan en el cliente

**Cuándo NO usar `"use client"`:**
- Solo para hacer fetch de datos (usar Server Component con `async/await`)
- Solo para leer variables de entorno del servidor
- Solo para acceder a la BD o servicios internos

```tsx
// MAL — "use client" innecesario para solo mostrar datos
'use client'

export default function ListaFacturas() {
  const [facturas, setFacturas] = useState([])
  useEffect(() => {
    fetch('/api/facturas').then(r => r.json()).then(setFacturas)
  }, [])
  return <ul>{facturas.map(f => <li key={f.id}>{f.folio}</li>)}</ul>
}

// BIEN — Server Component, fetch en el servidor
export default async function ListaFacturas() {
  const facturas = await obtenerFacturas()
  return <ul>{facturas.map(f => <li key={f.id}>{f.folio}</li>)}</ul>
}
```

---

## Convenciones de archivos del App Router

| Archivo | Propósito |
|---------|-----------|
| `page.tsx` | Ruta pública de la URL |
| `layout.tsx` | Layout compartido entre páginas del segmento |
| `loading.tsx` | UI de carga con Suspense automático |
| `error.tsx` | Boundary de error del segmento (`"use client"` obligatorio) |
| `not-found.tsx` | UI para `notFound()` |
| `route.ts` | Route handler (API endpoint) |
| `middleware.ts` | Middleware (solo en raíz del proyecto) |

- NUNCA crear un `page.tsx` con lógica de negocio. `page.tsx` solo orquesta
  componentes y pasa datos.

---

## Metadata API para SEO

```tsx
// MAL — Head component del Pages Router, obsoleto en App Router
import Head from 'next/head'
export default function Page() {
  return <><Head><title>Mi página</title></Head>...</>
}

// BIEN — Metadata API estática
export const metadata: Metadata = {
  title: 'Mi página',
  description: 'Descripción de la página',
}

// BIEN — Metadata API dinámica
export async function generateMetadata({ params }): Promise<Metadata> {
  const producto = await obtenerProducto(params.id)
  return { title: producto.nombre }
}
```

---

## Image y Link components obligatorios

```tsx
// MAL — <img> nativo sin optimización
<img src="/logo.png" alt="Logo" />

// BIEN — Image con optimización automática
import Image from 'next/image'
<Image src="/logo.png" alt="Logo" width={120} height={40} priority />

// MAL — <a> nativo sin prefetch
<a href="/facturas">Ver facturas</a>

// BIEN — Link con prefetch automático
import Link from 'next/link'
<Link href="/facturas">Ver facturas</Link>
```

---

## Longitud máxima: 100 líneas por componente

- Un componente que supera 100 líneas hace demasiado. Extraer subcomponentes.
- Colocar los subcomponentes en el mismo directorio que el componente padre si
  solo se usan ahí. Mover a `components/shared/` solo cuando se reutilizan.

---

## Checklist de estilo antes de hacer commit

- [ ] `next lint` pasa sin errores ni warnings
- [ ] `prettier --check .` pasa sin diferencias
- [ ] Sin `"use client"` que pueda eliminarse
- [ ] Imágenes con `<Image>`, no `<img>`
- [ ] Navegación con `<Link>`, no `<a>`
- [ ] SEO con Metadata API, no con `<Head>`
- [ ] Archivos nombrados según convenciones del App Router
- [ ] Componentes <= 100 líneas
