- Published on
Dominando el Enrutamiento en Next.js (Parte 1): Fundamentos y Estructura
- Authors

- Name
- Hidetoshi Yanagisawa
🚀 ¡Introducción!
Hola 👋
Hoy quiero compartir contigo algo que marcó un antes y un después en mi experiencia con Next.js: el enrutamiento con App Router.
Aunque pueda parecer un tema básico, entender bien cómo funciona te abre un abanico de posibilidades en el desarrollo web moderno.
Eso sí, el enrutamiento en Next.js tiene mucha miga.
Por eso este artículo es la primera parte de una guía completa.
Empecemos desde los cimientos.
- 🚀 ¡Introducción!
- 🧭 ¿Cómo se definen las rutas en Next.js?
- 🧱 Pages y Layouts
- 🎨 Templates
- 🧠 Metadata con head.tsx
- 🔗 Navegación entre rutas
- 🧭 Navegación programática
- 💡 Extra: History API
- ⏳ Loading UI
- 💥 Manejo de errores
- 🧩 Rutas Dinámicas: Introducción
- 🧶 Catch-all y Optional Catch-all
- ✅ Conclusión
🧭 ¿Cómo se definen las rutas en Next.js?
Next.js usa un sistema de enrutamiento basado en el sistema de archivos.
Dicho de otra forma: la estructura de carpetas y archivos dentro del directorio app/ define tus rutas.
Por ejemplo:
app/
|-- page.tsx
|-- dashboard/
| |-- page.tsx
| |-- settings/
| |-- page.tsx
Esto genera:
/→app/page.tsx/dashboard→app/dashboard/page.tsx/dashboard/settings→app/dashboard/settings/page.tsx
Solo los archivos llamados page.tsx (o .js, .jsx) que son default export se convierten en rutas. Los demás componentes (como los de app/components) no afectan al routing, aunque estén dentro de app/.
🧱 Pages y Layouts
En App Router, todo se basa en la colocación de archivos con nombres especiales. Veamos dos fundamentales: page.tsx y layout.tsx.
🔹 Pages
Son las páginas individuales: cada archivo page.tsx representa una ruta. Por ejemplo, si tienes esto:
app/
|-- page.tsx
|-- dashboard/
| |-- page.tsx
Se generan las rutas:
/conapp/page.tsx/dashboardconapp/dashboard/page.tsx
🔹 Layouts
Los layouts permiten definir una estructura común entre varias páginas. Por ejemplo, navegación lateral, headers, footers, etc.
// app/dashboard/layout.tsx
import type { ReactNode } from 'react'
export default function DashboardLayout({ children }: { children: ReactNode }) {
return (
<div>
<aside>Sidebar de Dashboard</aside>
<main>{children}</main>
</div>
)
}
Este layout envolverá a cualquier page.tsx dentro de la carpeta dashboard.
Además, los layouts mantienen su estado al navegar entre rutas hijas, lo que mejora la experiencia de usuario.
🎨 Templates
Similar a layout.tsx, pero con una diferencia clave: no mantienen estado entre rutas.
Cada vez que entras a una ruta que usa un template.tsx, se vuelve a renderizar.
Esto es útil para:
- Animaciones que deben reiniciarse al navegar
- Restablecer formularios
- Forzar recarga de componentes
La estructura es igual:
app/
|-- dashboard/
| |-- template.tsx
🧠 Metadata con head.tsx
¿SEO con React? Next.js lo tiene cubierto.
Usando un archivo head.tsx en cada ruta puedes definir:
<title><meta name="description" /><meta property="og:image" />
Ejemplo:
// app/dashboard/head.tsx
export default function Head() {
return (
<>
<title>Dashboard - Mi App</title>
<meta name="description" content="Panel de control personalizado" />
</>
)
}
🔗 Navegación entre rutas
Next.js ofrece varias formas de navegar:
✅ Link (Recomendado)
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">Ir al dashboard</Link>
}
- Es accesible (usa internamente
<a>) - Hace prefetch automático (precarga recursos)
- Ideal para navegación declarativa
💡 Soft Navigation
A diferencia de los sitios tradicionales, Next.js no recarga toda la página.
Solo actualiza las partes necesarias. Esto lo hace rápido como un rayo ⚡
🧭 Navegación programática
useRouter
Para usar en componentes cliente ('use client'):
'use client'
import { useRouter } from 'next/navigation'
export default function GoToDashboard() {
const router = useRouter()
return <button onClick={() => router.push('/dashboard')}>Ir</button>
}
redirect
En componentes del servidor:
import { redirect } from 'next/navigation'
export default async function Page() {
const isLoggedIn = await checkAuth()
if (!isLoggedIn) redirect('/login')
}
💡 Extra: History API
Puedes manipular el historial del navegador con window.history.
window.history.pushState(null, '', '?sort=asc')
window.history.replaceState(null, '', '/locale/en')
Útil para:
- Actualizar la URL sin recargar
- Navegaciones invisibles (como cambio de idioma)
⏳ Loading UI
Cuando los datos tardan en cargar, podemos mostrar un estado de carga.
Next.js permite esto con un archivo especial:
app/
|-- dashboard/
| |-- loading.tsx
Muestra lo que pongas allí mientras carga:
export default function Loading() {
return <p>Cargando...</p>
}
También puedes usar <Suspense> si prefieres algo más controlado.
💥 Manejo de errores
Puedes capturar errores por ruta con error.tsx:
app/
|-- dashboard/
| |-- error.tsx
Este archivo debe ser un cliente component:
'use client'
export default function Error({ error, reset }) {
return (
<div>
<h2>Algo salió mal</h2>
<button onClick={() => reset()}>Reintentar</button>
</div>
)
}
Si hay varios error.tsx, Next.js mostrará el más cercano en el árbol.
🧩 Rutas Dinámicas: Introducción
Puedes crear rutas como /blog/mi-articulo con esta estructura:
app/
|-- blog/
| |-- [slug]/
| |-- page.tsx
Y acceder al parámetro:
export default function Page({ params }: { params: { slug: string } }) {
return <h1>Post: {params.slug}</h1>
}
Para generar rutas estáticas, usa generateStaticParams():
export async function generateStaticParams() {
const posts = await fetchPosts()
return posts.map((post) => ({ slug: post.slug }))
}
🧶 Catch-all y Optional Catch-all
Puedes capturar múltiples segmentos con:
Catch-all
[...slug] → /shop/clothes/tops
Optional Catch-all
[[...slug]] → también coincide con /shop sin parámetros
✅ Conclusión
Hemos cubierto los fundamentos del enrutamiento con App Router en Next.js:
- Definir rutas con carpetas y archivos
- Reutilizar UI con layouts y templates
- Agregar SEO con
head.tsx - Navegar eficientemente con
LinkyuseRouter - Mostrar
loadingy capturarerrors - Crear rutas dinámicas
En la siguiente parte veremos cosas aún más poderosas 😎
¡Gracias por leer y feliz codificación!