- 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
/dashboard
conapp/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
head.tsx
🧠 Metadata con ¿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
Link
yuseRouter
- Mostrar
loading
y capturarerrors
- Crear rutas dinámicas
En la siguiente parte veremos cosas aún más poderosas 😎
¡Gracias por leer y feliz codificación!