EmDash trae conceptos familiares de WordPress—posts, páginas, taxonomías, menús, widgets y una biblioteca de medios—a un stack moderno de Astro. Tu conocimiento de gestión de contenido se transfiere directamente.
Lo que sigue siendo familiar
Los conceptos que conoces de WordPress son características de primera clase en EmDash:
- Collections funcionan como Custom Post Types—define tu estructura de contenido, consúltala en plantillas
- Taxonomías funcionan de la misma manera—jerárquicas (como categorías) y planas (como etiquetas)
- Menús con ordenación drag-and-drop y elementos anidados
- Áreas de widgets para barras laterales y regiones de contenido dinámico
- Biblioteca de medios con carga, organización y gestión de imágenes
- UI de administración que los editores de contenido pueden usar sin tocar código
Lo que es diferente
La implementación cambia, pero el modelo mental sigue siendo el mismo:
TypeScript en lugar de PHP
Las plantillas son componentes de Astro. La sintaxis es más limpia, pero el concepto es el mismo: código del servidor que genera HTML.
APIs de contenido en lugar de WP_Query
Funciones de consulta como getEmDashCollection() reemplazan WP_Query. Sin SQL, solo llamadas a funciones.
Enrutamiento basado en archivos
Los archivos en src/pages/ se convierten en URLs. Sin reglas de reescritura o jerarquía de plantillas que memorizar.
Componentes en lugar de template parts
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 UI de administración o API |
WP_Query | getEmDashCollection() | Filtros, límites, consultas de taxonomía |
get_post() | getEmDashEntry() | Devuelve entrada o null |
| Categorías/Etiquetas | Taxonomías | Soporte jerárquico preservado |
register_nav_menus() | getMenu() | Soporte de menú de primera clase |
register_sidebar() | getWidgetArea() | Áreas de widgets de primera clase |
bloginfo('name') | getSiteSetting("title") | API de configuración del sitio |
the_content() | <PortableText /> | Renderizado de contenido estructurado |
| Shortcodes | Bloques de Portable Text | Componentes personalizados |
add_action/filter() | Hooks de plugin | content:beforeSave, etc. |
wp_options | ctx.kv | Almacenamiento key-value |
| Directorio de tema | Directorio src/ | Componentes, layouts, páginas |
functions.php | astro.config.mjs + configuración de EmDash | Configuración de build y runtime |
APIs de contenido
Consultar Collections
Las consultas de 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
Los siguientes ejemplos obtienen una entrada por identificador y la renderizan, en WordPress y en EmDash:
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 seleccionar qué archivo renderiza una página. Astro usa enrutamiento explícito basado en archivos.
| Plantilla de WordPress | 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
Los template parts de WordPress se convierten en componentes de Astro:
WordPress
// En la plantilla:
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>La siguiente página importa ese componente y lo renderiza para cada post:
---
import PostCard from "../components/PostCard.astro";
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts");
---
{posts.map((post) => <PostCard {post} />)} Menús
EmDash tiene soporte de menú 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 a través de la UI de administración, archivos seed o importación de WordPress.
Áreas de widgets
Las áreas de widgets funcionan como las 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} />;
}
// Manejar otros tipos de widgets
})}
</aside>
)} Configuración del sitio
Las opciones del sitio y la configuración del customizer 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 |
El siguiente ejemplo lee configuraciones individuales con getSiteSetting():
import { getSiteSetting } from "emdash";
const title = await getSiteSetting("title");
const logo = await getSiteSetting("logo"); // Devuelve { mediaId, alt, url }
Taxonomías
Las taxonomías funcionan igual conceptualmente—jerárquicas (como categorías) o planas (como etiquetas):
import { getTaxonomyTerms, getEntryTerms, getTerm } from "emdash";
// Obtener todas las categorías
const categories = await getTaxonomyTerms("categories");
// Obtener un término específico
const news = await getTerm("categories", "news");
// Obtener términos para un post
const postCategories = await getEntryTerms("posts", postId, "categories");
Hooks → Sistema de plugins
Los hooks de WordPress (add_action, add_filter) se convierten en hooks de plugin de EmDash:
| Hook de WordPress | Hook de EmDash | Propósito |
|---|---|---|
save_post | content:beforeSave | Modificar contenido antes de guardar |
the_content | Componentes de PortableText | Transformar contenido renderizado |
pre_get_posts | Opciones de consulta | Filtrar consultas |
wp_head | Layout <head> | Agregar contenido de head |
wp_footer | Layout antes de </body> | Agregar contenido de footer |
Lo que es mejor en EmDash
Seguridad de tipos
TypeScript en todas partes. Las collections, consultas y componentes están completamente tipados, por lo que los nombres de campo y los tipos de retorno se autocompletn y se verifican en tiempo de compilación.
Rendimiento
Generación estática por defecto, con renderizado del servidor cuando sea necesario. Listo para despliegue en edge.
DX moderna
Hot Module Replacement. Arquitectura basada en componentes. Herramientas modernas (Vite, TypeScript, ESLint).
Despliegues basados en Git
El código y las plantillas viven en git; el contenido vive en la base de datos. Despliega haciendo push del código.
Enlaces de vista previa
EmDash genera URLs de vista previa seguras con tokens firmados HMAC. Los editores de contenido comparten un enlace de vista previa para mostrar un borrador, para que los revisores puedan verlo sin inicio de sesión en producción.
Plugins aislados
Los plugins de EmDash se ejecutan en contextos aislados con APIs explícitas. Cada plugin alcanza solo las APIs que declara, por lo que los plugins no comparten ni sobrescriben el estado global del otro.
Experiencia del editor de contenido
Los editores de contenido 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 rico para contenido (Portable Text, no Gutenberg)
- Biblioteca de medios con carga drag-and-drop
- Constructor de menús con ordenación drag-and-drop
- Editor de área de widgets para contenido de barra lateral
La experiencia de edición es familiar. La tecnología subyacente es moderna.
Ruta de migración
EmDash importa contenido de WordPress directamente:
- Exportar desde WordPress (Herramientas → Exportar)
- Subir el archivo
.xmlen el administrador de EmDash - Mapear post types a collections
- Importar contenido y medios
Posts, páginas, taxonomías, menús y medios se transfieren. Los bloques de Gutenberg se convierten a Portable Text. Los custom fields se analizan y mapean.
Consulta la Guía de migración de WordPress para instrucciones completas.
Próximos pasos
- Comenzando — Configura tu primer sitio EmDash
- Consultar contenido — Inmersión profunda en las APIs de contenido
- Taxonomías — Categorías, etiquetas y taxonomías personalizadas
- Menús — Menús de navegación
- Migrar desde WordPress — Importar contenido existente