32blogby StudioMitsu

Claude Code × Next.js: Evita los Errores de App Router Generados por IA

Los 7 errores más comunes de App Router que Claude Code genera, cómo prevenirlos con CLAUDE.md y cómo usar next-devtools-mcp para un ciclo de feedback en tiempo real.

11 min read
Contenido

Claude Code puede crear una página de Next.js en segundos. El problema es que esa página podría usar patrones de 2023.

Las herramientas de codificación con IA se entrenan con datasets masivos que incluyen años de código de Pages Router, patrones anteriores a App Router y prácticas de React desactualizadas. Cuando le pides a Claude Code que construya una funcionalidad de Next.js 16, a menudo genera código que parece correcto pero viola las convenciones de App Router de formas sutiles y difíciles de detectar.

Este artículo cubre los 7 errores más comunes de App Router que Claude Code genera, cómo prevenirlos con la configuración correcta de CLAUDE.md y cómo usar el servidor MCP integrado de Next.js 16 para un ciclo de feedback de errores en tiempo real.

CLAUDE.mdReglas de App RouterRestringirAGENTS.mdReferencia a docs incluidosFundamentarnext-devtools-mcpErrores en tiempo realValidarCódigo CorrectoSin errores silenciosos

Por Qué Claude Code Se Equivoca con App Router

El problema central es simple: los datos de entrenamiento de Claude contienen mucho más código de Pages Router que de App Router. Pages Router fue el estándar durante 7 años (2016–2023). App Router se estabilizó en Next.js 13.4 (mayo 2023) — apenas hace 3 años.

Esto significa que el "instinto predeterminado" de Claude Code se inclina hacia patrones como:

  • getServerSideProps en lugar de Server Components asíncronos
  • useRouter de next/router en lugar de next/navigation
  • Route Handlers para todo en lugar de Server Actions para mutaciones
  • useEffect para obtención de datos en lugar de acceso directo en Server Components

CLAUDE.md ayuda, pero no es suficiente por sí solo. Claude puede seguir tus reglas al inicio de la sesión y gradualmente volver a patrones antiguos a medida que el contexto se llena.

La solución real es una defensa de tres capas:

  1. CLAUDE.md — reglas explícitas que Claude lee al inicio de sesión
  2. AGENTS.md — dirige a Claude a los docs de Next.js incluidos en node_modules para referencia precisa por versión
  3. next-devtools-mcp — alimenta errores de build y errores de tipo a Claude en tiempo real

Los 7 Errores Más Comunes de Next.js Generados por IA

Estos provienen del blog oficial de Vercel, reportes de la comunidad y tres meses de desarrollo diario con Claude Code + Next.js.

1. Llamar Route Handlers desde Server Components

typescript
// MAL — viaje de red innecesario
// app/users/page.tsx (Server Component)
export default async function UsersPage() {
  const res = await fetch("http://localhost:3000/api/users");
  const users = await res.json();
  return <UserList users={users} />;
}
typescript
// BIEN — acceso directo a la base de datos en Server Component
// app/users/page.tsx (Server Component)
import { db } from "@/lib/db";

export default async function UsersPage() {
  const users = await db.user.findMany();
  return <UserList users={users} />;
}

Los Server Components se ejecutan en el servidor. Pueden acceder a bases de datos, sistemas de archivos y APIs internas directamente. Llamar a tu propio Route Handler crea una solicitud HTTP innecesaria a ti mismo.

2. Uso excesivo de "use client"

typescript
// MAL — toda la página se convierte en Client Component
"use client";

export default function DashboardPage() {
  // Todo aquí se envía al navegador
}
typescript
// BIEN — solo el componente interactivo es Client Component
// app/dashboard/page.tsx (Server Component — sin directiva)
import { InteractiveChart } from "./interactive-chart";

export default async function DashboardPage() {
  const data = await fetchDashboardData();
  return (
    <div>
      <h1>Dashboard</h1>
      <StaticSummary data={data} />
      <InteractiveChart data={data} />
    </div>
  );
}

"use client" solo debe aparecer en los componentes hoja interactivos más pequeños. Claude tiende a agregarlo a archivos de nivel de página ante la primera señal de interactividad.

3. Ubicación incorrecta de Suspense Boundary

tsx
// MAL — Suspense envuelve el componente equivocado
export default function Page() {
  return <AsyncDataComponent />;
}

async function AsyncDataComponent() {
  const data = await fetchData();
  return (
    <Suspense fallback={<Loading />}>
      <DataView data={data} />
    </Suspense>
  );
}
tsx
// BIEN — Suspense envuelve el componente asíncrono desde AFUERA
export default function Page() {
  return (
    <Suspense fallback={<Loading />}>
      <AsyncDataComponent />
    </Suspense>
  );
}

async function AsyncDataComponent() {
  const data = await fetchData();
  return <DataView data={data} />;
}

Suspense debe envolver el componente que desencadena la operación asíncrona, desde el nivel padre. Colocarlo dentro del componente asíncrono anula su propósito.

4. Metadata en Client Components

typescript
// MAL — el export de metadata se ignora en Client Components
"use client";

export const metadata = { title: "Dashboard" };
typescript
// BIEN — metadata debe estar en un Server Component (page.tsx o layout.tsx)
// app/dashboard/page.tsx (sin "use client")
export const metadata = { title: "Dashboard" };

El export metadata solo funciona en Server Components. Si Claude agrega "use client" a un archivo de página, metadata deja de funcionar silenciosamente sin mensaje de error.

5. Falta de revalidation en Server Actions

typescript
// MAL — la UI no se actualiza después de la mutación
"use server";

export async function createPost(formData: FormData) {
  await db.post.create({ data: { title: formData.get("title") as string } });
  // La UI muestra datos obsoletos
}
typescript
// BIEN — revalidar la ruta afectada
"use server";

import { revalidatePath } from "next/cache";

export async function createPost(formData: FormData) {
  await db.post.create({ data: { title: formData.get("title") as string } });
  revalidatePath("/posts");
}

6. Usar redirect() dentro de try/catch

typescript
// MAL — redirect lanza internamente, es capturado por try/catch
"use server";

export async function loginAction(formData: FormData) {
  try {
    await authenticate(formData);
    redirect("/dashboard"); // Esto lanza NEXT_REDIRECT, capturado abajo
  } catch (error) {
    return { error: "Login failed" }; // El redirect nunca ocurre
  }
}
typescript
// BIEN — redirect fuera de try/catch
"use server";

export async function loginAction(formData: FormData) {
  let success = false;
  try {
    await authenticate(formData);
    success = true;
  } catch (error) {
    return { error: "Login failed" };
  }
  if (success) redirect("/dashboard");
}

redirect() funciona lanzando un error especial NEXT_REDIRECT. Si está dentro de try/catch, el redirect es absorbido.

7. Acceso síncrono a Request APIs (Next.js 16)

typescript
// MAL — acceso síncrono eliminado en Next.js 16
import { cookies } from "next/headers";

export default function Page() {
  const cookieStore = cookies(); // Error de build en Next.js 16
}
typescript
// BIEN — acceso asíncrono requerido
import { cookies } from "next/headers";

export default async function Page() {
  const cookieStore = await cookies();
}

Next.js 16 eliminó completamente el acceso síncrono a cookies(), headers(), params y searchParams. Claude frecuentemente genera la versión síncrona a partir de datos de entrenamiento antiguos.


Configuración de CLAUDE.md para Proyectos Next.js

Aquí hay un CLAUDE.md práctico que previene los errores anteriores.

markdown
# Project: Next.js 16 App Router

## Tech Stack
- Next.js 16.1 + TypeScript strict + Tailwind CSS v4
- App Router only. No Pages Router patterns
- React Server Components by default

## Critical Rules
- NEVER add "use client" to page.tsx or layout.tsx unless the entire page must be interactive
- NEVER call Route Handlers from Server Components — access data directly
- ALWAYS use async/await for cookies(), headers(), params, searchParams
- ALWAYS place Suspense boundaries OUTSIDE the async component
- ALWAYS call revalidatePath() or revalidateTag() in Server Actions after mutations
- NEVER put redirect() inside try/catch blocks

## Data Fetching
- Server Components: direct database/API access (no fetch to own Route Handlers)
- Client Components: Server Actions for mutations, Route Handlers only for third-party webhooks
- Cache: use the "use cache" directive for explicit caching

## Reference
- Read AGENTS.md for bundled Next.js docs location
- When unsure about an API, check node_modules/next/dist/docs/ first

AGENTS.md y Docs Incluidos

Next.js 16 incluye documentación dentro de node_modules/next/dist/docs/. El AGENTS.md generado automáticamente le indica a las herramientas de IA que consulten estos docs antes de generar código, asegurando orientación precisa por versión sin importar la antigüedad de los datos de entrenamiento.

Esta es la forma más efectiva de prevenir errores de "patrones antiguos." En lugar de depender de la memoria de Claude sobre las APIs de Next.js, lee los docs reales de la versión que tienes instalada.


next-devtools-mcp — El Puente de IA Integrado en Next.js 16

Next.js 16 incluye un endpoint /_next/mcp que expone el estado del servidor de desarrollo a herramientas de IA. El paquete next-devtools-mcp conecta Claude Code a este endpoint.

Configuración

Agrega a .mcp.json en la raíz de tu proyecto:

json
{
  "mcpServers": {
    "next-devtools": {
      "command": "npx",
      "args": ["-y", "next-devtools-mcp@latest"]
    }
  }
}

Luego inicia tu servidor de desarrollo (npm run dev) y Claude Code se conectará automáticamente.

Qué proporciona

HerramientaQué hace
get_errorsRetorna errores de build, errores de runtime y errores de tipo en tiempo real
get_logsAcceso a la salida de consola del servidor de desarrollo
get_page_metadataEstructura de rutas, tipos de componentes, modo de renderizado por página
get_project_metadataConfiguración del proyecto, versión de Next.js, URL del servidor de desarrollo
get_server_action_by_idLocalizar el archivo fuente de un Server Action específico

Por qué esto importa

Sin MCP, el ciclo de feedback es: Claude escribe código → tú notas un error de build → lo pegas de vuelta → Claude lo arregla. Con next-devtools-mcp, Claude ve el error inmediatamente y puede auto-corregirse antes de que tú lo notes.

Esto es especialmente poderoso para el tipo de errores listados arriba. Una ubicación incorrecta de Suspense podría no lanzar un error visible pero aparecerá en get_page_metadata como comportamiento de renderizado inesperado.


Un Flujo de Trabajo Real con Claude Code × Next.js

Aquí está el flujo de trabajo que funciona para desarrollo diario de Next.js con Claude Code.

1. Configuración de sesión

bash
# Iniciar servidor de desarrollo en segundo plano
npm run dev

# Iniciar Claude Code
claude

Claude Code se conecta a next-devtools-mcp automáticamente. Ejecuta /context para verificar que MCP está cargado.

2. Ciclo de desarrollo de funcionalidades

  1. Describe la funcionalidad que quieres
  2. Claude genera código — CLAUDE.md previene los 7 errores comunes
  3. next-devtools-mcp retroalimenta cualquier error en tiempo real
  4. Claude se auto-corrige sin necesidad de que pegues errores
  5. Revisa el código generado para corrección lógica

3. Validación pre-commit

Usa un PostToolUse Hook para ejecutar automáticamente la verificación de tipos después de ediciones:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "npx tsc --noEmit --pretty 2>&1 | head -20"
          }
        ]
      }
    ]
  }
}

4. Gestión de contexto

  • /compact cuando trabajas en una funcionalidad por mucho tiempo
  • /clear cuando cambias a una funcionalidad diferente
  • Session-handoff.md para trabajo multi-sesión

Para una inmersión profunda en estrategias de gestión de contexto, consulta "Por Qué Claude Code Olvida y Cómo Solucionarlo."


Conclusión

Claude Code es notablemente capaz en desarrollo de Next.js — una vez que le das las barreras correctas.

CapaQué haceEsfuerzo de configuración
CLAUDE.mdPreviene los 7 errores comunes de App Router5 minutos
AGENTS.mdFundamenta a Claude en docs de Next.js precisos por versiónAutomático con create-next-app
next-devtools-mcpCiclo de feedback de errores en tiempo real2 minutos
HooksEjecuta verificaciones de tipo automáticamente después de ediciones5 minutos

El patrón es simple: restringir con CLAUDE.md, fundamentar con docs incluidos, validar con MCP. Configura estas tres capas correctamente y Claude Code dejará de generar patrones de 2023 para tu codebase de 2026.

Artículos relacionados: