EmDash para desarrolladores de WordPress

En esta página

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

WordPressEmDashNotas
Custom Post TypesCollectionsDefinir vía UI de administración o API
WP_QuerygetEmDashCollection()Filtros, límites, consultas de taxonomía
get_post()getEmDashEntry()Devuelve entrada o null
Categorías/EtiquetasTaxonomíasSoporte 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
ShortcodesBloques de Portable TextComponentes personalizados
add_action/filter()Hooks de plugincontent:beforeSave, etc.
wp_optionsctx.kvAlmacenamiento key-value
Directorio de temaDirectorio src/Componentes, layouts, páginas
functions.phpastro.config.mjs + configuración de EmDashConfiguració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 WordPressEquivalente en EmDash
index.phpsrc/pages/index.astro
single.phpsrc/pages/posts/[slug].astro
single-{type}.phpsrc/pages/{type}/[slug].astro
page.phpsrc/pages/pages/[slug].astro
archive.phpsrc/pages/posts/index.astro
archive-{type}.phpsrc/pages/{type}/index.astro
category.phpsrc/pages/categories/[slug].astro
tag.phpsrc/pages/tags/[slug].astro
search.phpsrc/pages/search.astro
404.phpsrc/pages/404.astro
header.php / footer.phpsrc/layouts/Base.astro
sidebar.phpsrc/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():

WordPressEmDash
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 WordPressHook de EmDashPropósito
save_postcontent:beforeSaveModificar contenido antes de guardar
the_contentComponentes de PortableTextTransformar contenido renderizado
pre_get_postsOpciones de consultaFiltrar consultas
wp_headLayout <head>Agregar contenido de head
wp_footerLayout 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:

  1. Exportar desde WordPress (Herramientas → Exportar)
  2. Subir el archivo .xml en el administrador de EmDash
  3. Mapear post types a collections
  4. 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