Páginas y Layouts

Recomendamos leer las páginas Fundamentos de Enrutamiento y Definiendo Rutas antes de continuar.

Los archivos especiales layout.js, page.js, y template.js te permiten crear UI para una ruta. Esta página te guiará sobre cómo y cuándo usar estos archivos especiales.

Páginas

Una página es una UI única para una ruta. Puedes definir una página exportando por defecto un componente desde un archivo page.js.

Por ejemplo, para crear tu página index, añade el archivo page.js dentro del directorio app:

Archivo especial page.js
// `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>
}

Luego, para crear más páginas, crea una nueva carpeta y añade el archivo page.js dentro. Por ejemplo, para crear una página para la ruta /dashboard, crea una carpeta llamada dashboard, y añade el archivo page.js dentro:

// `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>
}

Bueno saber:

Layouts

Un layout es una UI compartida entre múltiples rutas. En la navegación, los layouts preservan el estado, permanecen interactivos 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 durante el renderizado.

Por ejemplo, el layout se compartirá con las páginas /dashboard y /dashboard/settings:

Archivo especial layout.js
export default function DashboardLayout({
  children, // será una página o layout anidado
}: {
  children: React.ReactNode
}) {
  return (
    <section>
      {/* Incluye UI compartida aquí, como 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í, como un encabezado o barra lateral */}
      <nav></nav>

      {children}
    </section>
  )
}

Root Layout (Obligatorio)

El root layout se define en el nivel superior del directorio app y se aplica a todas las rutas. Este layout es obligatorio y debe contener etiquetas html y body, permitiéndote modificar el HTML inicial devuelto desde el servidor.

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        {/* UI del Layout */}
        <main>{children}</main>
      </body>
    </html>
  )
}
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {/* UI del Layout */}
        <main>{children}</main>
      </body>
    </html>
  )
}

Anidando Layouts

Por defecto, los layouts en la jerarquía de carpetas están anidados, lo que significa que envuelven layouts hijos a través de su prop children. Puedes anidar layouts añadiendo layout.js dentro de segmentos de ruta específicos (carpetas).

Por ejemplo, para crear un layout para la ruta /dashboard, añade un nuevo archivo layout.js dentro de la carpeta dashboard:

Layout Anidado
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return <section>{children}</section>
}
export default function DashboardLayout({ children }) {
  return <section>{children}</section>
}

Si combinaras los dos layouts anteriores, el root layout (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í:

Layouts Anidados

Bueno saber:

Templates

Los templates 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, los templates 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 un template, 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 los templates 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) y useState (ej. un formulario de feedback por página).
  • Para cambiar el comportamiento predeterminado del framework. Por ejemplo, los Suspense Boundaries dentro de layouts solo muestran el fallback la primera vez que se carga el Layout y no al cambiar páginas. Para templates, el fallback se muestra en cada navegación.

Un template puede definirse exportando por defecto un componente React desde un archivo template.js. El componente debe aceptar una prop children.

Archivo especial template.js
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:

Output
<Layout>
  {/* Nota que al template se le da una clave única. */}
  <Template key={routeParam}>{children}</Template>
</Layout>

Metadata

En el directorio app, puedes modificar los elementos HTML <head> como title y meta usando las APIs de Metadata.

La metadata puede 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 '...'
}

Bueno saber: No debes añadir manualmente etiquetas <head> como <title> y <meta> a root layouts. En su lugar, debes usar la API de Metadata que maneja automáticamente requisitos avanzados como streaming y deduplicación de elementos <head>.

Aprende más sobre las opciones de metadata disponibles en la referencia de API