Ir al contenido

Astro para Desarrolladores de WordPress

Astro es un framework web para construir sitios web centrados en contenido. Al usar EmDash, Astro reemplaza tu tema de WordPress: maneja la plantilla, el enrutamiento y la renderización.

Esta guía enseña los fundamentos de Astro mapeándolos a conceptos de WordPress que ya comprendes.

Renderizado en el servidor por defecto

Como PHP, el código de Astro se ejecuta en el servidor. A diferencia de PHP, genera HTML estático por defecto sin JavaScript.

Cero JS a menos que lo añadas

WordPress carga jQuery y scripts del tema automáticamente. Astro no envía nada al navegador a menos que lo añadas explícitamente.

Arquitectura basada en componentes

En lugar de etiquetas de plantilla e includes dispersos, construye con componentes componibles y autocontenidos.

Enrutamiento basado en archivos

Sin reglas de reescritura o query_vars. La estructura de archivos en src/pages/ define tus URLs directamente.

Los temas de WordPress tienen una estructura plana con nombres de archivo mágicos. Astro usa directorios explícitos:

WordPressAstroPropósito
index.php, single.phpsrc/pages/Rutas (URLs)
template-parts/src/components/Piezas de UI reutilizables
header.php + footer.phpsrc/layouts/Envoltorios de página
style.csssrc/styles/CSS global
functions.phpastro.config.mjsConfiguración del sitio

Un proyecto típico de Astro podría verse así:

src/
├── components/ # Reusable UI (Header, PostCard, etc.)
├── layouts/ # Page shells (Base.astro)
├── pages/ # Routes - files become URLs
│ ├── index.astro # → /
│ ├── posts/
│ │ ├── index.astro # → /posts
│ │ └── [slug].astro # → /posts/hello-world
│ └── [slug].astro # → /about, /contact, etc.
└── styles/
└── global.css

Los archivos .astro son el equivalente de Astro a las plantillas PHP. Cada archivo tiene dos partes:

  1. Frontmatter (entre cercas ---) — Código del lado del servidor, como PHP en la parte superior de una plantilla
  2. Plantilla — HTML con expresiones, como el resto de una plantilla PHP
src/components/PostCard.astro
---
// Frontmatter: runs on server, never sent to browser
interface Props {
title: string;
excerpt: string;
url: string;
}
const { title, excerpt, url } = Astro.props;
---
<!-- Template: outputs HTML -->
<article class="post-card">
<h2><a href={url}>{title}</a>
</h2>
<p>{excerpt}</p>
</article>

Diferencias clave con PHP:

  • El Frontmatter está aislado. Las variables declaradas allí están disponibles en la plantilla, pero el código en sí nunca llega al navegador.
  • Las importaciones van en el frontmatter. Componentes, datos, utilidades: todo se importa en la parte superior.
  • TypeScript funciona. Define tipos de props con interface Props para autocompletado del editor y validación.

Las plantillas de Astro usan {curly braces} en lugar de etiquetas <?php ?>. La sintaxis es similar a JSX pero genera HTML puro.

src/components/PostList.astro
---
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts");
const showTitle = true;
---
{showTitle && <h1>Entradas recientes</h1>}
{posts.length > 0 ? (
<ul>
{posts.map(post => (
<li>
<a href={`/posts/${post.id}`}>{post.data.title}</a>
</li>
))}
</ul>
) : (
<p>No se encontraron entradas.</p>
)}
PatrónPropósito
{variable}Mostrar un valor
{condition && <Element />}Renderizado condicional
{condition ? <A /> : <B />}If/else
{items.map(item => <Li>{item}</Li>)}Bucles

Los componentes reciben datos a través de props (como argumentos de función) y slots (como puntos de inserción de do_action).

src/components/Card.astro
---
interface Props {
title: string;
featured?: boolean;
}
const { title, featured = false } = Astro.props;
---
<article class:list={["card", { featured }]}>
<h2>{title}</h2>
<slot />
<slot name="footer" />
</article>

Uso:

<Card title="Hello" featured>
<p>Este contenido va al slot principal.</p>
<footer slot="footer">Contenido del pie</footer>
</Card>

En WordPress, get_template_part() pasa datos a través del array $args. Las props de Astro están tipadas y se desestructuran:

---
// Type-safe with defaults
interface Props {
title: string;
count?: number;
}
const { title, count = 10 } = Astro.props;
---

WordPress usa do_action() para crear puntos de inserción. Astro usa slots:

WordPressAstro
do_action('before_content')<slot name="before" />
Área de contenido por defecto<slot />
do_action('after_content')<slot name="after" />

La diferencia: los slots reciben elementos hijos en el sitio de llamada, mientras que los hooks de WordPress requieren llamadas add_action() separadas en otro lugar.

Los layouts envuelven páginas con una estructura HTML común: el <head>, el encabezado, el pie de página y cualquier cosa compartida entre páginas. Esto reemplaza header.php + footer.php.

src/layouts/Base.astro
---
import "../styles/global.css";
interface Props {
title: string;
description?: string;
}
const { title, description = "Mi sitio con EmDash" } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content={description} />
<title>{title}</title>
</head>
<body>
<header>
<nav><!-- Navigation --></nav>
</header>
<main>
<slot />
</main>
<footer>
<p>&copy; {new Date().getFullYear()}</p>
</footer>
</body>
</html>

Usa el layout en una página:

src/pages/index.astro
---
import Base from "../../layouts/Base.astro";
---
<Base title="Inicio">
<h1>Bienvenido</h1>
<p>El contenido de la página se inserta en el slot.</p>
</Base>

Astro ofrece varios enfoques de estilización. El más distintivo son los estilos con alcance.

Los estilos en una etiqueta <style> se limitan automáticamente a ese componente:

src/components/Card.astro
<article class="card">
<h2>Título</h2>
</article>
<style>
/* Solo afecta a .card en ESTE componente */
.card {
padding: 1rem;
border: 1px solid #ddd;
}
h2 {
color: navy;
}
</style>

El HTML generado incluye nombres de clase únicos para evitar fugas de estilos. Se acabaron las guerras de especificidad.

Para estilos de todo el sitio, crea un archivo CSS e impórtalo en un layout:

src/layouts/Base.astro
---
import "../styles/global.css";
---

La directiva class:list reemplaza la construcción manual de cadenas de clases:

---
const { featured, size = "medium" } = Astro.props;
---
<article class:list={[
"card",
size,
{ featured, "has-border": true }
]}>

Salida: <article class="card medium featured has-border">

Astro no envía JavaScript por defecto. Este es el mayor cambio mental respecto a WordPress.

Para interacciones simples, añade una etiqueta <script>:

src/components/MobileMenu.astro
<button id="menu-toggle">Menú</button>
<nav id="mobile-menu" hidden>
<slot />
</nav>
<script>
const toggle = document.getElementById("menu-toggle");
const menu = document.getElementById("mobile-menu");
toggle?.addEventListener("click", () => {
menu?.toggleAttribute("hidden");
});
</script>

Los scripts se agrupan y deduplican automáticamente. Si este componente aparece dos veces en una página, el script se ejecuta una sola vez.

Para interactividad más compleja, Astro puede cargar componentes de JavaScript (React, Vue, Svelte) bajo demanda. Esto es opcional: la mayoría de los sitios funcionan bien solo con etiquetas <script>.

src/pages/index.astro
---
import SearchWidget from "../../components/SearchWidget.jsx";
---
<!-- Only load JavaScript when the search box scrolls into view -->
<SearchWidget client:visible />
DirectivaCuándo se carga JavaScript
client:loadInmediatamente al cargar la página
client:visibleCuando el componente entra en el viewport
client:idleCuando el navegador está inactivo

Astro utiliza enrutamiento basado en archivos. Los archivos en src/pages/ se convierten en URLs:

ArchivoURL
src/pages/index.astro/
src/pages/about.astro/about
src/pages/posts/index.astro/posts
src/pages/posts/[slug].astro/posts/hello-world
src/pages/[...slug].astroCualquier ruta (catch-all)

Para contenido de un CMS, usa la sintaxis de corchetes para segmentos dinámicos:

src/pages/posts/[slug].astro
---
import { getEmDashCollection, getEmDashEntry } from "emdash";
import Base from "../../../layouts/Base.astro";
import { PortableText } from "emdash/ui";
// For static builds, define which pages to generate
export async function getStaticPaths() {
const { entries: posts } = await getEmDashCollection("posts");
return posts.map(post => ({
params: { slug: post.id },
props: { post },
}));
}
const { post } = Astro.props;
---
<Base title={post.data.title}>
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>
</Base>
WordPressAstro
Jerarquía de plantillas (single-post.php)Archivo explícito: posts/[slug].astro
Reglas de reescritura + query_varsEstructura de archivos
$wp_query determina la plantillaLa URL se mapea directamente al archivo
add_rewrite_rule()Crear archivos o carpetas

Una referencia para encontrar el equivalente en Astro/EmDash de las características de WordPress:

WordPressAstro/EmDash
Jerarquía de plantillasEnrutamiento basado en archivos en src/pages/
get_template_part()Importar y usar componentes
the_content()<PortableText value={content} />
the_title(), the_*()Acceder vía post.data.title
Etiquetas de plantillaExpresiones de plantilla {value}
body_class()Directiva class:list
WordPressAstro/EmDash
WP_QuerygetEmDashCollection(type, filters)
get_post()getEmDashEntry(type, id)
get_posts()getEmDashCollection(type)
get_the_terms()Acceder vía entry.data.categories
get_post_meta()Acceder vía entry.data.fieldName
get_option()getSiteSettings()
wp_nav_menu()getMenu(location)
WordPressAstro/EmDash
add_action()Hooks de EmDash, middleware de Astro
add_filter()Hooks de EmDash
add_shortcode()Bloques personalizados de Portable Text
register_block_type()Bloques personalizados de Portable Text
register_sidebar()Áreas de widgets de EmDash
PluginsIntegraciones de Astro + plugins de EmDash
WordPressAstro/EmDash
register_post_type()Crear colección en la interfaz de administración
register_taxonomy()Crear taxonomía en la interfaz de administración
register_meta()Añadir campo al esquema de la colección
Estado de la entradaEstado de la entrada (borrador, publicado, etc.)
Imagen destacadaCampo de referencia a medios
Bloques de GutenbergBloques de Portable Text

El salto de WordPress a Astro es significativo pero lógico:

  1. Plantillas PHP → Componentes Astro — Misma idea (código del servidor + HTML), mejor organización
  2. Etiquetas de plantilla → Props e importaciones — Flujo de datos explícito en lugar de variables globales
  3. Archivos de tema → Directorio de páginas — Las URLs coinciden con la estructura de archivos
  4. Hooks → Slots y middleware — Puntos de inserción más predecibles
  5. jQuery por defecto → Cero JS por defecto — Añadir interactividad de forma intencionada

Comienza con la guía Primeros pasos para construir tu primer sitio EmDash, o explora Trabajar con contenido para aprender cómo consultar y renderizar datos del CMS.