Dominando los Layouts en Astro: Cómo usar Slots y Props para crear páginas consistentes

DUGLAS MORENODUGLAS MORENO 👁 17

Si estás empezando con Astro, probablemente ya te diste cuenta de que es un framework increíble para generar sitios estáticos rápidos. Pero a medida que tu proyecto crece, te topás con un problema clásico: no querés estar copiando y pegando el mismo HTML del header, el footer y las meta-tags en cada una de tus páginas. Ahí es donde entran los Layouts.

En este artículo vamos a profundizar en cómo diseñar layouts robustos utilizando Slots (para el contenido dinámico) y Props (para personalizar datos como el título de la página). Si sos desarrollador frontend y querés optimizar tu flujo de trabajo en Astro, este post es para vos.

¿Qué es exactamente un Layout en Astro?

Básicamente, un Layout es un componente de Astro que actúa como un "molde" o envoltorio para otras páginas. En lugar de definir la estructura completa de HTML en cada archivo .astro de tu carpeta pages/, creás un componente dedicado que define la arquitectura global y luego "inyectás" el contenido específico de cada página dentro de él.

La magia ocurre gracias a dos conceptos fundamentales:

  1. Props: Permiten pasar datos desde la página hacia el layout (por ejemplo, el título de la pestaña del navegador).
  2. Slots: Son marcadores de posición donde Astro renderiza el contenido que ponés dentro de las etiquetas del Layout.

Paso 1: Creando tu primer Layout Base

Lo ideal es organizar tus layouts en una carpeta dedicada, por ejemplo src/layouts/. Vamos a crear un archivo llamado MainLayout.astro.

En este ejemplo, vamos a definir que el layout reciba un título y una descripción a través de props para mejorar el SEO de cada página.

---
// src/layouts/MainLayout.astro
const { title, description = "Mi sitio hecho con Astro" } = Astro.props;
---

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content={description} />
    <title>{title} | Mi Blog Técnico</title>
    <style>
        body { font-family: system-ui, sans-serif; margin: 0; padding: 0; }
        nav { background: #333; color: white; padding: 1rem; display: flex; gap: 1rem; }
        nav a { color: white; text-decoration: none; }
        main { padding: 2rem; max-width: 800px; margin: 0 auto; }
        footer { text-align: center; padding: 2rem; background: #eee; margin-top: 2rem; }
    </style>
</head>
<body>
    <nav>
        <a href="/">Inicio</a>
        <a href="/blog">Blog</a>
        <a href="/contacto">Contacto</a>
    </nav>

    <main>
        <slot /> <!-- Aquí es donde se inyectará el contenido de la página -->
    </main>

    <footer>
        <p>&copy; 2024 - Desarrollado con Astro y mucho café</p>
    </footer>
</body>
</html>

Análisis del código:

  • Astro.props: Es el objeto que contiene todas las propiedades pasadas al componente. Desestructuramos title y description (le damos un valor por defecto a esta última).
  • <slot />: Es la pieza clave. Sin esto, el contenido de tus páginas jamás se mostraría. El slot le dice a Astro: "Poné todo lo que esté dentro del componente Layout justo acá".

Paso 2: Implementando el Layout en tus páginas

Ahora que tenemos el molde, usarlo es sumamente sencillo. Solo tenés que importar el Layout en tu página y envolver el contenido.

---
// src/pages/index.astro
import MainLayout from '../layouts/MainLayout.astro';
---

<MainLayout title="Inicio" description="Bienvenido a mi portfolio técnico">
    <h1>Hola, soy un Dev Fullstack</h1>
    <p>Acá vas a encontrar tutoriales sobre bases de datos, Astro y más.</p>
    <p>Fijate cómo este contenido se renderiza dentro del slot del layout.</p>
</MainLayout>

Salida esperada en el navegador:

El resultado final será un documento HTML completo donde el contenido de index.astro se insertará dentro de la etiqueta <main> del MainLayout.astro. El título de la pestaña será "Inicio | Mi Blog Técnico".

Paso 3: Layouts Avanzados con Named Slots (Slots Nombrados)

A veces, un solo <slot /> no es suficiente. Imaginate que querés que algunas páginas tengan un banner especial arriba del contenido principal, o un sidebar lateral, pero que no todas las páginas lo tengan.

Para esto usamos los Named Slots. Podés definir múltiples slots dándoles un nombre mediante el atributo name.

Actualicemos nuestro MainLayout.astro para agregar un slot para un banner:

---
// src/layouts/MainLayout.astro (Versión mejorada)
const { title } = Astro.props;
---

<!DOCTYPE html>
<html lang="es">
<head>
    <title>{title}</title>
    <style>
        .banner { background: #ffcc00; padding: 1rem; text-align: center; font-weight: bold; }
        main { padding: 2rem; }
    </style>
</head>
<body>
    <nav>...</nav>

    <!-- Slot nombrado para el banner -->
    <slot name="banner" />

    <main>
        <slot /> <!-- Slot por defecto -->
    </main>

    <footer>...</footer>
</body>
</html>

Ahora, en tu página, podés decidir qué contenido va en cada slot usando la propiedad slot="nombre":

---
// src/pages/promocion.astro
import MainLayout from '../layouts/MainLayout.astro';
---

<MainLayout title="Oferta Especial">
    <div slot="banner" class="banner">
        🚀 ¡Cursos de Astro con 50% de descuento solo por hoy!
    </div>

    <h1>Bienvenido a la sección de ofertas</h1>
    <p>Acá tenés el contenido normal que va al slot por defecto.</p>
</MainLayout>

Salida esperada:

  1. El div con slot="banner" se renderizará arriba del contenido principal, justo donde pusimos <slot name="banner" />.
  2. El resto del HTML (el h1 y el p) se renderizará en el <slot /> general.

Llevando la lógica al siguiente nivel: Componentes Dinámicos

Para que veas el poder de Astro, podemos combinar Layouts con lógica de JavaScript pura en el frontmatter. Supongamos que querés que el layout cambie el color del header dependiendo de una prop.

---
// src/layouts/ThemedLayout.astro
const { themeColor = '#333' } = Astro.props;
---
<style define:vars={{ themeColor }}>
    nav { background-color: var(--themeColor); color: white; padding: 1rem; }
</style>

<nav>
    <a href="/">Inicio</a>
</nav>
<slot />

Podés probar esto con un pequeño script de Python si quisieras simular la generación de colores dinámicos para tus páginas antes de pasarlos a Astro:

import random

def generate_random_color():
    return "#{:06x}".format(random.randint(0, 0xFFFFFF))

colors = [generate_random_color() for _ in range(3)]
print(f"Sugerencias de colores para tus layouts: {colors}")

Buenas Prácticas y Errores Comunes

✅ Recomendaciones:

  • Crea un Layout Base y Layouts Derivados: Podés tener un BaseLayout con el HTML básico y luego un PostLayout que envuelva al BaseLayout pero agregue estilos específicos para artículos (como tipografía de lectura).
  • Usa valores por defecto en las Props: Siempre definí valores default para evitar que el sitio rompa si olvidás pasar una prop en alguna página.
  • Mantén el CSS Global separado: Aunque Astro permite estilos en los componentes, para el layout base es recomendable usar un archivo CSS global o la directiva <style is:global> para evitar duplicaciones.

❌ Errores frecuentes:

  • Olvidar el <slot />: Es el error más común. Si tu página está en blanco pero no hay errores en la consola, revisá si pusiste el slot en el layout.
  • Confundir Props con Estado: Recordá que Astro es principalmente un generador de sitios estáticos. Las props que pasás al Layout se procesan en el servidor (durante el build), no en el cliente. Si necesitás interactividad, usá componentes de framework (React, Vue, Svelte) dentro del layout.
  • Anidar demasiados Layouts: Si tenés 5 niveles de layouts, el código se vuelve difícil de seguir. Intentá mantener la estructura plana: BaseLayout $
    ightarrow$ PageLayout $
    ightarrow$ Content.

Conclusión

Implementar layouts con slots y props en Astro no solo hace que tu código sea más limpio y mantenible, sino que te permite escalar tu proyecto sin volverte loco editando 20 páginas cada vez que querés cambiar un link en el menú.

Resumen rápido:

  • Props: Para datos dinámicos (títulos, metas, colores).
  • Slot por defecto: Para el cuerpo principal de la página.
  • Named Slots: Para secciones específicas (banners, sidebars, modales).

Ahora te toca a vos. Intentá crear un layout complejo que maneje diferentes estados visuales según la sección del sitio y optimizá ese flujo de trabajo. ¡A programar!

Comentarios (0)

Sé el primero en comentar.

Dejá tu comentario