🚀 Astro Cheatsheet Completo 🚀

Astro es un framework web de JavaScript todo-en-uno que te permite construir sitios web rápidos y centrados en el contenido con una experiencia de desarrollo moderna. Su principal diferenciador es que envía cero JavaScript al cliente por defecto, lo que resulta en tiempos de carga y métricas de rendimiento (Core Web Vitals) excepcionales. Utiliza una arquitectura de “Islas” para hidratar solo los componentes interactivos.


1. 🌟 Conceptos Clave


2. 🛠️ Configuración Inicial

  1. Crear un Nuevo Proyecto Astro:

    npm create astro@latest # O `yarn create astro@latest` o `pnpm create astro@latest`
    # Seguir las indicaciones (ej. proyecto vacío, instalar dependencias, inicializar git)
    • Esto crea:
      • src/pages/: Directorio para tus páginas.
      • src/components/: Directorio para tus componentes Astro/UI.
      • src/layouts/: Directorio para tus layouts.
      • src/content/: Directorio para colecciones de contenido (blogs, etc.).
      • public/: Archivos estáticos (imágenes, favicons) servidos directamente.
      • astro.config.mjs: Archivo de configuración principal.
  2. Iniciar el Servidor de Desarrollo:

    npm run dev
    # Visita http://localhost:4321/
  3. Construir para Producción:

    npm run build
    # Genera una carpeta `dist/` con archivos optimizados.
  4. Previsualizar el Build de Producción:

    npm run preview

3. 🧩 Componentes Astro (.astro)

Son el tipo de archivo principal en Astro. Combinan un “código de frontal” (frontmatter/script) para la lógica y un “template” para el HTML.

3.1. Estructura de un Componente Astro

---
// 1. Código de Frontal (Frontmatter / Script de Componente)
// JavaScript/TypeScript que se ejecuta SÓLO en el servidor (en tiempo de build o de solicitud)
import MyReactComponent from '../components/MyReactComponent.jsx'; // Importa componentes de UI
import { format } from 'date-fns'; // Importa librerías Node.js
import someData from '../data/mydata.json'; // Carga JSON/YAML/etc.

// Definir y obtener props (se accede vía Astro.props)
const { title, description, imageUrl, tags = [] } = Astro.props;

// Variables y lógica que se usarán en el template
const formattedDate = format(new Date(), 'yyyy-MM-dd');
const isFeatured = tags.includes('featured');

// Funciones o importaciones que no son para el cliente
const serverSideFunction = () => { /* ... */ };
---
<!-- 2. Template (HTML + JSX-like) -->
<!-- El HTML de este componente se renderiza en el servidor -->
<div class="card">
  <h2>{{ title }}</h2> {# Renderiza variables del script de componente #}
  <img src="{{ imageUrl }}" alt="{{ title }}">
  <p>{{ description }}</p>

  <ul class="tags">
    {# Bucles (v-for equivalente) #}
    {% for tag in tags %}
      <li>{{ tag }}</li>
    {% endfor %}
  </ul>

  {# Renderizado condicional (v-if equivalente) #}
  <div class="featured" astro:ignore-self v-if="isFeatured">Destacado!</div>
  {# Astro permite lógica de JS directamente #}
  {isFeatured && <p>¡Este artículo es especial!</p>}

  <p>Fecha de publicación: {{ formattedDate }}</p>

  &lt;!-- Slots: para inyectar contenido desde el componente padre -->
  <slot /> {# Slot por defecto #}
  <slot name="footer" /> {# Slot con nombre #}

  &lt;!-- Importar componentes de otros frameworks de UI -->
  &lt;!-- Directivas client:* para hidratar componentes en el cliente -->
  <MyReactComponent client:load message="¡Hola desde React!" />

  <button class="button" onclick="alert('Hola!')">Clickeame (JS Vanilla)</button>
</div>

<style>
/* Estilos CSS (scoped por defecto, como en Vue) */
.card {
  border: 1px solid #ccc;
  padding: 1rem;
  margin-bottom: 1rem;
  border-radius: 8px;
}
h2 {
  color: var(--astro-colors-primary); /* Acceso a variables CSS de Astro */
}
</style>

3.2. Props en Componentes Astro

3.3. Slots

Permiten que un componente padre inyecte contenido en un componente hijo.


4. 🗺️ Enrutamiento (File-based Routing)

Las páginas se definen en el directorio src/pages/.

4.1. getStaticPaths() (Para Rutas Dinámicas SSG)

Función necesaria en los archivos [slug].astro para generar rutas estáticamente en tiempo de construcción.

&lt;!-- src/pages/blog/[slug].astro -->
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import { getCollection } from 'astro:content'; // Para colecciones de contenido

// getStaticPaths se ejecuta en tiempo de build
export async function getStaticPaths() {
  const blogPosts = await getCollection('blog'); // Obtiene todos los posts de la colección 'blog'

  return blogPosts.map((post) =&gt; ({
    params: { slug: post.slug }, // Define el parámetro dinámico de la URL
    props: { post }, // Pasa el objeto post como prop al componente de página
  }));
}

// Acceder a las props pasadas desde getStaticPaths
const { post } = Astro.props; // `post` es el objeto de colección de contenido
---
<BaseLayout title={post.data.title}>
  <h1>{{ post.data.title }}</h1>
  <p>Publicado en: {{ post.data.pubDate.toLocaleDateString() }}</p>
  <hr>
  <div class="content">
    <Content /> {# Componente Content para renderizar Markdown/MDX #}
  </div>
</BaseLayout>

5. 🎨 Estilización


6. 🌐 Integraciones (UI Frameworks & Herramientas)

Astro es extensible a través de “integraciones”.

  1. Añadir una Integración (CLI):

    npx astro add react # Añade soporte para React
    npx astro add vue   # Añade soporte para Vue
    # ... y muchas otras (solid, svelte, lit, preact, tailwind, mdx, etc.)
    • Esto actualiza tu astro.config.mjs automáticamente.
  2. Uso de Componentes de UI Frameworks:

    • Simplemente impórtalos y úsalos en tus archivos .astro.
    • Directivas de cliente (client:*): ¡CRÍTICO! Indican cuándo y cómo un componente de UI debe hidratarse (ejecutarse en el cliente). Si no se usa, el componente se renderiza en el servidor como HTML estático.
      • client:load: Hidrata el componente tan pronto como la página carga y el JavaScript es accesible.
      • client:idle: Hidrata el componente cuando el navegador está inactivo.
      • client:visible: Hidrata el componente cuando entra en el viewport del usuario.
      • client:media={query}: Hidrata cuando una media query CSS es verdadera (ej. client:media="(max-width: 600px)").
      • client:only={framework}: Hidrata solo en el cliente (no pre-renderiza en el servidor), útil para componentes que dependen de APIs del navegador. (ej. <MyComponent client:only="react" />)
    &lt;!-- src/pages/index.astro -->
    ---
    import MyReactCounter from '../components/MyReactCounter.jsx';
    import MyVueComponent from '../components/MyVueComponent.vue';
    ---
    <main>
      <h1>Página con Islas</h1>
      <MyReactCounter client:load initialCount={0} /> {# Se hidrata al cargar la página #}
      <MyVueComponent client:visible message="Solo cuando sea visible" /> {# Se hidrata al scroll #}
    </main>

7. 📚 Colecciones de Contenido (src/content/)

Para gestionar contenido estructurado (blogs, proyectos, autores) con tipado seguro.

7.1. Definir un Esquema (src/content/config.ts)

// src/content/config.ts
import { defineCollection, z } from 'astro:content';

const blogCollection = defineCollection({
  type: 'content', // 'content' para Markdown/MDX, 'data' para JSON/YAML
  schema: z.object({
    title: z.string(),
    description: z.string(),
    pubDate: z.date(),
    author: z.string().default('Anónimo'),
    image: z.string().optional(),
    tags: z.array(z.string()).default([]),
  }),
});

// Exporta un objeto `collections` con tus colecciones
export const collections = {
  'blog': blogCollection,
  // 'projects': projectCollection,
};

7.2. Crear Contenido (src/content/blog/my-first-post.md)

---
title: Mi Primer Post en Astro
description: Este es el contenido de mi primer post.
pubDate: 2023-10-26T10:00:00Z
author: Juan Pérez
tags: ["tutorial", "astro"]
---
¡Hola a todos!

Este es el contenido de mi post escrito en **Markdown**.

Puedes usar:
- Listas
- **Negritas**
- *Cursivas*

7.3. Consultar Contenido en Páginas/Componentes

&lt;!-- src/pages/blog/index.astro -->
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import { getCollection } from 'astro:content'; // Para consultar colecciones

const allBlogPosts = await getCollection('blog'); // Obtiene todos los posts de la colección 'blog'
---
<BaseLayout title="Blog">
  <h1>Nuestro Blog</h1>
  <ul>
    {% for post in allBlogPosts %}
      <li>
        <a href="/blog/{{ post.slug }}">
          <h3>{{ post.data.title }}</h3>
          <p>{{ post.data.description }}</p>
          <small>{{ post.data.pubDate.toLocaleDateString() }} por {{ post.data.author }}</small>
        </a>
      </li>
    {% endfor %}
  </ul>
</BaseLayout>

8. 📁 API Routes (src/pages/api/)

Permite construir endpoints API RESTful o GraphQL directamente en tu proyecto Astro.


9. 💡 Buenas Prácticas y Consejos


Este cheatsheet te proporciona una referencia completa de Astro, cubriendo sus conceptos esenciales, estructura de componentes, enrutamiento, estilización, integraciones, colecciones de contenido y las mejores prácticas para construir sitios web de alto rendimiento.