Páginas y Layouts
Recomendamos leer las páginas Fundamentos de Enrutamiento y Definiendo Rutas antes de continuar.
El App Router en Next.js 13 introdujo nuevas convenciones de archivos para crear fácilmente páginas, layouts compartidos y plantillas. Esta guía te mostrará cómo usar estos archivos especiales en tu aplicación Next.js.
Páginas
Una página es una interfaz de usuario única para una ruta. Puedes definir páginas exportando un componente desde un archivo page.js
. Usa carpetas anidadas para definir una ruta y un archivo page.js
para hacer la ruta accesible públicamente.
Crea tu primera página añadiendo un archivo page.js
dentro del directorio app
:

// `app/page.tsx` es la UI para la URL `/`
export default function Page() {
return <h1>¡Hola, página de inicio!</h1>
}
// `app/page.js` es la UI para la URL `/`
export default function Page() {
return <h1>¡Hola, página de inicio!</h1>
}
// `app/dashboard/page.tsx` es la UI para la URL `/dashboard`
export default function Page() {
return <h1>¡Hola, página de Dashboard!</h1>
}
// `app/dashboard/page.js` es la UI para la URL `/dashboard`
export default function Page() {
return <h1>¡Hola, página de Dashboard!</h1>
}
Es bueno saber:
- Una página siempre es la hoja del subárbol de rutas.
- Se pueden usar extensiones de archivo
.js
,.jsx
o.tsx
para Páginas.- Se requiere un archivo
page.js
para hacer un segmento de ruta accesible públicamente.- Las páginas son Componentes del Servidor (Server Components) por defecto pero pueden configurarse como Componentes del Cliente (Client Components).
- Las páginas pueden obtener datos. Consulta la sección Obtención de Datos (Data Fetching) para más información.
Layouts
Un layout es una interfaz de usuario compartida entre múltiples páginas. En la navegación, los layouts preservan el estado, mantienen la interactividad y no se vuelven a renderizar. Los layouts también pueden estar anidados.
Puedes definir un layout exportando por defecto un componente React desde un archivo layout.js
. El componente debe aceptar una prop children
que se llenará con un layout hijo (si existe) o una página hija durante el renderizado.

export default function DashboardLayout({
children, // será una página o layout anidado
}: {
children: React.ReactNode
}) {
return (
<section>
{/* Incluye UI compartida aquí, ej. un encabezado o barra lateral */}
<nav></nav>
{children}
</section>
)
}
export default function DashboardLayout({
children, // será una página o layout anidado
}) {
return (
<section>
{/* Incluye UI compartida aquí, ej. un encabezado o barra lateral */}
<nav></nav>
{children}
</section>
)
}
Es bueno saber:
- El layout superior se llama Root Layout (Layout Raíz). Este layout requerido es compartido por todas las páginas en una aplicación. Los layouts raíz deben contener etiquetas
html
ybody
.- Cualquier segmento de ruta puede opcionalmente definir su propio Layout. Estos layouts serán compartidos por todas las páginas en ese segmento.
- Los layouts en una ruta están anidados por defecto. Cada layout padre envuelve los layouts hijos debajo de él usando la prop
children
de React.- Puedes usar Grupos de Rutas (Route Groups) para incluir o excluir segmentos de ruta específicos de layouts compartidos.
- Los layouts son Componentes del Servidor (Server Components) por defecto pero pueden configurarse como Componentes del Cliente (Client Components).
- Los layouts pueden obtener datos. Consulta la sección Obtención de Datos (Data Fetching) para más información.
- No es posible pasar datos entre un layout padre y sus hijos. Sin embargo, puedes obtener los mismos datos en una ruta múltiples veces, y React deduplicará automáticamente las solicitudes sin afectar el rendimiento.
- Los layouts no tienen acceso a los segmentos de ruta debajo de sí mismos. Para acceder a todos los segmentos de ruta, puedes usar
useSelectedLayoutSegment
ouseSelectedLayoutSegments
en un Componente del Cliente.- Se pueden usar extensiones de archivo
.js
,.jsx
o.tsx
para Layouts.- Un archivo
layout.js
ypage.js
pueden definirse en la misma carpeta. El layout envolverá la página.
Root Layout (Obligatorio)
El layout raíz se define en el nivel superior del directorio app
y aplica a todas las rutas. Este layout te permite modificar el HTML inicial devuelto desde el servidor.
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="es">
<body>{children}</body>
</html>
)
}
export default function RootLayout({ children }) {
return (
<html lang="es">
<body>{children}</body>
</html>
)
}
Es bueno saber:
- El directorio
app
debe incluir un layout raíz.- El layout raíz debe definir las etiquetas
<html>
y<body>
ya que Next.js no las crea automáticamente.- Puedes usar el soporte SEO integrado para manejar elementos HTML
<head>
, por ejemplo, el elemento<title>
.- Puedes usar grupos de rutas (route groups) para crear múltiples layouts raíz. Consulta un ejemplo aquí.
- El layout raíz es un Componente del Servidor (Server Component) por defecto y no puede configurarse como Componente del Cliente (Client Component).
Migrando desde el directorio
pages
: El layout raíz reemplaza los archivos_app.js
y_document.js
. Consulta la guía de migración.
Anidando Layouts
Los layouts definidos dentro de una carpeta (ej. app/dashboard/layout.js
) aplican a segmentos de ruta específicos (ej. acme.com/dashboard
) y se renderizan cuando esos segmentos están activos. Por defecto, los layouts en la jerarquía de archivos están anidados, lo que significa que envuelven layouts hijos a través de su prop children
.

export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
export default function DashboardLayout({ children }) {
return <section>{children}</section>
}
Es bueno saber:
- Solo el layout raíz puede contener las etiquetas
<html>
y<body>
.
Si combinaras los dos layouts anteriores, el layout raíz (app/layout.js
) envolvería el layout del dashboard (app/dashboard/layout.js
), que a su vez envolvería los segmentos de ruta dentro de app/dashboard/*
.
Los dos layouts estarían anidados así:

Puedes usar Grupos de Rutas (Route Groups) para incluir o excluir segmentos de ruta específicos de layouts compartidos.
Plantillas
Las plantillas son similares a los layouts en que envuelven cada layout hijo o página. A diferencia de los layouts que persisten entre rutas y mantienen el estado, las plantillas crean una nueva instancia para cada uno de sus hijos en la navegación. Esto significa que cuando un usuario navega entre rutas que comparten una plantilla, se monta una nueva instancia del componente, se recrean los elementos DOM, el estado no se preserva y los efectos se resincronizan.
Puede haber casos donde necesites esos comportamientos específicos, y las plantillas serían una opción más adecuada que los layouts. Por ejemplo:
- Características que dependen de
useEffect
(ej. registro de visitas de página) yuseState
(ej. un formulario de retroalimentación por página). - Para cambiar el comportamiento predeterminado del framework. Por ejemplo, los Límites de Suspense (Suspense Boundaries) dentro de layouts solo muestran el fallback la primera vez que se carga el Layout y no al cambiar páginas. Para plantillas, el fallback se muestra en cada navegación.
Una plantilla puede definirse exportando por defecto un componente React desde un archivo template.js
. El componente debe aceptar una prop children
.

export default function Template({ children }: { children: React.ReactNode }) {
return <div>{children}</div>
}
export default function Template({ children }) {
return <div>{children}</div>
}
En términos de anidación, template.js
se renderiza entre un layout y sus hijos. Aquí hay una salida simplificada:
<Layout>
{/* Nota que la plantilla recibe una clave única. */}
<Template key={routeParam}>{children}</Template>
</Layout>
Modificando <head>
En el directorio app
, puedes modificar elementos HTML <head>
como title
y meta
usando el soporte SEO integrado.
Los metadatos pueden definirse exportando un objeto metadata
o una función generateMetadata
en un archivo layout.js
o page.js
.
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
export const metadata = {
title: 'Next.js',
}
export default function Page() {
return '...'
}
Es bueno saber: No deberías añadir manualmente etiquetas
<head>
como<title>
y<meta>
a los layouts raíz. En su lugar, usa la API de Metadatos (Metadata API) que maneja automáticamente requisitos avanzados como streaming y deduplicación de elementos<head>
.
Aprende más sobre las opciones de metadatos disponibles en la referencia de API.