Saltar al contenido

Anatomía de un componente .astro

La estructura de un archivo .astro diseccionada pieza a pieza: la valla del frontmatter delimitada por la triple barra, la plantilla HTML que cuelga debajo, y qué responsabilidad asume cada zona dentro del modelo de dos tiempos de Astro 7.

Un archivo, dos zonas

Un .astro se lee de arriba abajo en dos tramos. Arriba, entre dos líneas de triple guion, vive el frontmatter del componente —también llamado component script—: JavaScript o TypeScript que Astro ejecuta cuando construye la página. Debajo de la segunda valla se extiende la plantilla: un superconjunto de HTML donde insertas los valores calculados arriba. El compilador lee el archivo, separa ambas zonas y las trata de forma radicalmente distinta.

La analogía con el frontmatter de Markdown es deliberada. En un .md, la triple barra encierra metadatos —título, fecha— que no se imprimen en la página. En un .astro, esa misma valla encierra código que sí produce efectos, pero comparte la propiedad esencial: lo que hay entre las barras no aparece literalmente en la salida. Es preparación, no contenido.

ASTRO
---// zona 1: la valla del frontmatter (component script)const titulo = "Hola, Astro 7";const items = ["uno", "dos", "tres"];---<!-- zona 2: la plantilla HTML --><h1>{titulo}</h1><ul>  {items.map((item) => <li>{item}</li>)}</ul>

Ese archivo entero es un componente. No hay clase, no hay función render, no hay un export default obligatorio: la estructura misma del archivo —valla arriba, HTML abajo— es la declaración del componente. Astro infiere el resto a partir de la forma.

El compilador de Astro —escrito en Rust, como viste en el primer nivel— no lee este archivo como HTML con código incrustado, sino casi al revés: lo transforma en un módulo cuyo valor exportado es una función de renderizado que devuelve marcado. Esa inversión explica por qué la valla manda sobre la plantilla: primero se ejecuta el código, y solo después se arma el HTML con lo que ese código dejó preparado. El flujo va siempre en un sentido, de la valla hacia la plantilla, nunca de vuelta.

La valla: la triple barra —

La secuencia --- cumple una función sintáctica exacta: abre y cierra la zona de código. La primera aparición marca el inicio del frontmatter; la segunda, su fin y el comienzo de la plantilla. Entre ambas escribes código como lo harías en un módulo de JavaScript, con una diferencia decisiva: se ejecuta una sola vez, del lado del constructor, nunca en el navegador del visitante.

Dentro de la valla mandan las reglas de un módulo ES. import trae dependencias, const y let declaran variables, y el await de nivel superior está permitido porque el frontmatter es asíncrono por naturaleza. Lo que escribes aquí no es un lenguaje de plantillas inventado: es JavaScript o TypeScript real, con toda su potencia y sin dialecto propietario que memorizar.

ASTRO
---import Boton from '../components/Boton.astro';const ahora = new Date();const saludo = ahora.getHours() < 12 ? "Buenos dias" : "Buenas tardes";---<p>{saludo}</p><Boton />

En esas pocas líneas conviven las tres tareas que más repetirás en una valla: importar una dependencia, calcular un valor derivado y preparar los datos que la plantilla consumirá. Ninguna de las tres viaja al navegador; solo lo hace la cadena de texto que la variable saludo termine valiendo en el instante del renderizado.

La plantilla: HTML debajo de la valla

Bajo la segunda barra empieza la plantilla, y su base es HTML corriente: las mismas etiquetas y los mismos atributos que escribirías en un .html. La diferencia es que Astro la trata como un superconjunto. Acepta expresiones entre llaves —{titulo}— que interpolan los valores calculados en la valla, y admite componer otros componentes, algo que verás en lecciones posteriores.

Un detalle que sorprende a quien viene de React: no necesitas un único elemento raíz. Un .astro puede emitir varios elementos hermanos en su nivel superior sin envolverlos en un fragmento. La plantilla no es una expresión que deba resolver a un solo nodo, sino la descripción de un fragmento de documento que se insertará donde se use el componente.

ASTRO
---const productos = ["Teclado", "Raton", "Monitor"];const hayStock = productos.length > 0;---<h2>Catalogo</h2>{hayStock  ? <ul>{productos.map((p) => <li>{p}</li>)}</ul>  : <p>Sin existencias</p>}

No te detengas aún en la mecánica de esas expresiones —las llaves, el map, el ternario—: son el tema de una lección posterior. Aquí basta con reconocer la silueta del archivo. Arriba, el catálogo se declara como un dato normal de JavaScript; abajo, la plantilla lo proyecta en marcado. La valla piensa, la plantilla muestra.

El modelo mental: composición y renderizado

Un mismo .astro desempeña dos papeles según dónde viva. Colocado en src/pages, es una página: se renderiza a una ruta del sitio. Colocado en src/components, es un componente: se compone dentro de otros. La anatomía no cambia —valla y plantilla— pero el propósito sí, y esa dualidad es la razón de que Astro no distinga sintácticamente entre página y componente.

Leer la anatomía con esta doble lente evita un error común: creer que las páginas y los componentes son cosas distintas. No lo son. Una página es simplemente un componente que Astro decidió mapear a una URL por vivir en src/pages. Todo lo que aprendas sobre la valla y la plantilla vale para ambos por igual.

ASTRO
---// una pagina: mismo formato, devuelve el documento completoimport Saludo from '../components/Saludo.astro';---<html lang="es">  <body>    <Saludo />  </body></html>

La única diferencia práctica es de contrato: una página suele devolver un documento HTML completo —con html, head y body— mientras que un componente devuelve un fragmento pensado para encajar dentro de otro. Pero esa distinción la impone tu diseño, no la sintaxis del archivo: Astro trata a ambos con las mismas reglas de valla y plantilla.