EmDash lleva conceptos familiares de WordPress—entradas, páginas, taxonomías, menús, widgets y una biblioteca de medios—a un stack moderno con Astro. Tu conocimiento de gestión de contenidos se transfiere directamente.
Lo que sigue siendo familiar
Los conceptos que conoces de WordPress son funciones de primera clase en EmDash:
- Collections funcionan como Custom Post Types—define la estructura del contenido y consúltala en las plantillas
- Taxonomies igual—jerárquicas (como categorías) y planas (como etiquetas)
- Menus con orden por arrastrar y soltar y elementos anidados
- Widget Areas para barras laterales y regiones de contenido dinámico
- Media library con subida, organización y gestión de imágenes
- Admin UI que los editores pueden usar sin tocar código
Qué cambia
La implementación cambia, pero el modelo mental se mantiene:
TypeScript en lugar de PHP
Las plantillas son componentes Astro. La sintaxis es más limpia, pero el concepto es el mismo: código en el servidor que genera HTML.
Content APIs en lugar de WP_Query
Funciones de consulta como getEmDashCollection() sustituyen a WP_Query. Sin SQL, solo llamadas a funciones.
Enrutado basado en archivos
Los archivos en src/pages/ se convierten en URLs. Sin reglas de reescritura ni jerarquía de plantillas que memorizar.
Componentes en lugar de partes de plantilla
Importa y usa componentes. Misma idea que get_template_part(), mejor organización.
Referencia rápida
| WordPress | EmDash | Notas |
|---|---|---|
| Custom Post Types | Collections | Definir vía admin UI o API |
WP_Query | getEmDashCollection() | Filtros, límites, consultas por taxonomía |
get_post() | getEmDashEntry() | Devuelve entrada o null |
| Categories/Tags | Taxonomies | Se mantiene el soporte jerárquico |
register_nav_menus() | getMenu() | Menús de primera clase |
register_sidebar() | getWidgetArea() | Áreas de widgets de primera clase |
bloginfo('name') | getSiteSetting("title") | API de ajustes del sitio |
the_content() | <PortableText /> | Renderizado de contenido estructurado |
| Shortcodes | Portable Text blocks | Componentes personalizados |
add_action/filter() | Plugin hooks | content:beforeSave, etc. |
wp_options | ctx.kv | Almacenamiento clave-valor |
| Theme directory | src/ directory | Componentes, layouts, páginas |
functions.php | astro.config.mjs + EmDash config | Configuración de build y tiempo de ejecución |
Content APIs
Consultar collections
Las consultas en WordPress usan WP_Query o funciones auxiliares. EmDash usa funciones de consulta tipadas.
WordPress
<?php
$posts = new WP_Query([
'post_type' => 'post',
'posts_per_page' => 10,
'post_status' => 'publish',
'category_name' => 'news',
]);
while ($posts->have_posts()) :
$posts->the_post();
?>
<h2><?php the_title(); ?></h2>
<?php the_excerpt(); ?>
<?php endwhile; ?> EmDash
---
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
limit: 10,
where: { category: "news" },
});
---
{posts.map((post) => (
<article>
<h2>{post.data.title}</h2>
<p>{post.data.excerpt}</p>
</article>
))} Obtener una sola entrada
WordPress
<?php
$post = get_post($id);
?>
<article>
<h1><?php echo $post->post_title; ?></h1>
<?php echo apply_filters('the_content', $post->post_content); ?>
</article> EmDash
---
import { getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";
const { slug } = Astro.params;
const { entry: post } = await getEmDashEntry("posts", slug);
## if (!post) return Astro.redirect("/404");
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article> Jerarquía de plantillas
WordPress usa una jerarquía de plantillas para elegir qué archivo renderiza una página. Astro usa enrutado explícito basado en archivos.
| WordPress Template | Equivalente en EmDash |
|---|---|
index.php | src/pages/index.astro |
single.php | src/pages/posts/[slug].astro |
single-{type}.php | src/pages/{type}/[slug].astro |
page.php | src/pages/pages/[slug].astro |
archive.php | src/pages/posts/index.astro |
archive-{type}.php | src/pages/{type}/index.astro |
category.php | src/pages/categories/[slug].astro |
tag.php | src/pages/tags/[slug].astro |
search.php | src/pages/search.astro |
404.php | src/pages/404.astro |
header.php / footer.php | src/layouts/Base.astro |
sidebar.php | src/components/Sidebar.astro |
Template parts → Componentes
Las partes de plantilla de WordPress se convierten en componentes Astro:
WordPress
// In template:
get_template_part('template-parts/content', 'post');
// template-parts/content-post.php:
<article class="post">
<h2><?php the_title(); ?></h2>
<?php the_excerpt(); ?>
</article> EmDash
---
const { post } = Astro.props;
---
<article class="post">
<h2>{post.data.title}</h2>
<p>{post.data.excerpt}</p>
</article>---
import PostCard from "../components/PostCard.astro";
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts");
---
{posts.map((post) => <PostCard {post} />)} Menús
EmDash ofrece menús de primera clase con resolución automática de URL:
WordPress
<?php
wp_nav_menu([
'theme_location' => 'primary',
'container' => 'nav',
]);
?> EmDash
---
import { getMenu } from "emdash";
## const menu = await getMenu("primary");
<nav>
<ul>
{menu?.items.map((item) => (
<li>
<a href={item.url}>{item.label}</a>
</li>
))}
</ul>
</nav> Los menús se crean desde la admin UI, archivos seed o importación de WordPress.
Áreas de widgets
Las áreas de widgets funcionan como barras laterales en WordPress:
WordPress
<?php if (is_active_sidebar('sidebar-1')) : ?>
<aside>
<?php dynamic_sidebar('sidebar-1'); ?>
</aside>
<?php endif; ?> EmDash
---
import { getWidgetArea } from "emdash";
import { PortableText } from "emdash/ui";
## const sidebar = await getWidgetArea("sidebar");
{sidebar && (
<aside>
{sidebar.widgets.map((widget) => {
if (widget.type === "content") {
return <PortableText value={widget.content} />;
}
// Handle other widget types
})}
</aside>
)} Ajustes del sitio
Las opciones del sitio y del personalizador se mapean a getSiteSetting():
| WordPress | EmDash |
|---|---|
bloginfo('name') | getSiteSetting("title") |
bloginfo('description') | getSiteSetting("tagline") |
get_custom_logo() | getSiteSetting("logo") |
get_option('date_format') | getSiteSetting("dateFormat") |
home_url() | Astro.site |
import { getSiteSetting } from "emdash";
const title = await getSiteSetting("title");
const logo = await getSiteSetting("logo"); // Returns { mediaId, alt, url }
Taxonomías
Las taxonomías son conceptualmente iguales—jerárquicas (como categorías) o planas (como etiquetas):
import { getTaxonomyTerms, getEntryTerms, getTerm } from "emdash";
// Get all categories
const categories = await getTaxonomyTerms("categories");
// Get a specific term
const news = await getTerm("categories", "news");
// Get terms for a post
const postCategories = await getEntryTerms("posts", postId, "categories");
Hooks → Sistema de plugins
Los hooks de WordPress (add_action, add_filter) pasan a ser hooks de plugins de EmDash:
| WordPress Hook | EmDash Hook | Propósito |
|---|---|---|
save_post | content:beforeSave | Modificar contenido antes de guardar |
the_content | PortableText components | Transformar el contenido renderizado |
pre_get_posts | Query options | Filtrar consultas |
wp_head | Layout <head> | Añadir contenido en el head |
wp_footer | Layout before </body> | Añadir contenido en el footer |
Qué mejora en EmDash
Seguridad de tipos
TypeScript en todo el proyecto. Collections, consultas y componentes totalmente tipados. Se acabó adivinar nombres de campos o tipos de retorno.
Rendimiento
Sin sobrecarga de PHP. Generación estática por defecto. Render en servidor cuando hace falta. Listo para despliegue en edge.
DX moderna
Hot module replacement. Arquitectura basada en componentes. Herramientas actuales (Vite, TypeScript, ESLint).
Despliegues basados en Git
Código y plantillas en git. Contenido en la base de datos. Sin FTP, sin permisos de archivos, sin sitios hackeados.
Enlaces de vista previa
EmDash genera URL de vista previa seguras con tokens firmados HMAC. Los editores pueden previsualizar borradores sin iniciar sesión en producción—comparten un enlace, no credenciales.
Sin conflictos entre plugins
Desaparecen los conflictos típicos de plugins en WordPress. Los plugins de EmDash se ejecutan en contextos aislados con APIs explícitas. Sin contaminación de estado global.
Experiencia del editor de contenido
Los editores usan el panel de administración de EmDash, similar a wp-admin:
- Dashboard con actividad reciente
- Listados de collections con búsqueda, filtros y acciones masivas
- Editor enriquecido para contenido (Portable Text, no Gutenberg)
- Biblioteca de medios con subida por arrastrar y soltar
- Constructor de menús con orden por arrastrar y soltar
- Editor de áreas de widgets para contenido en la barra lateral
La experiencia de edición es familiar. La tecnología debajo es moderna.
Ruta de migración
EmDash importa contenido de WordPress directamente:
- Exportar desde WordPress (Herramientas → Exportar)
- Subir el archivo
.xmlen el admin de EmDash - Mapear tipos de entrada a collections
- Importar contenido y medios
Se transfieren entradas, páginas, taxonomías, menús y medios. Los bloques de Gutenberg se convierten a Portable Text. Los campos personalizados se analizan y mapean.
Consulta la guía de migración desde WordPress para instrucciones completas.
Próximos pasos
- Getting Started — Configura tu primer sitio EmDash
- Querying Content — Profundiza en las Content APIs
- Taxonomies — Categorías, etiquetas y taxonomías personalizadas
- Menus — Menús de navegación
- Migrate from WordPress — Importa contenido existente