Published on

Dominando el Enrutamiento en Next.js (Parte 1): Fundamentos y Estructura

Authors

🚀 ¡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.


🧭 ¿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
  • /dashboardapp/dashboard/page.tsx
  • /dashboard/settingsapp/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:

  • / con app/page.tsx
  • /dashboard con app/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:

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 y useRouter
  • Mostrar loading y capturar errors
  • Crear rutas dinámicas

En la siguiente parte veremos cosas aún más poderosas 😎

¡Gracias por leer y feliz codificación!