Porte um tema WordPress separando seu design, seus templates de rota e os recursos gerenciados pelo banco de dados. O resultado é um projeto Astro completo, com consultas do EmDash e um arquivo seed, e não um tema PHP carregado por um runtime de temas.
Comece pelo conteúdo e pelas URLs
Importe conteúdo representativo antes de converter os templates. Registre os tipos de conteúdo do WordPress, as taxonomias, as regras de links permanentes, os menus, as áreas de widgets, os valores do Customizer, os shortcodes e a marcação gerada por plugins usados pelo site.
Escolha a nova URL de cada tipo de conteúdo. As rotas do Astro são arquivos explícitos, portanto não há um equivalente automático da hierarquia de templates do WordPress.
O template de blog atual usa este mapeamento:
| WordPress | Caminho do template do EmDash |
|---|---|
front-page.php ou home.php | src/pages/index.astro |
single.php | src/pages/posts/[slug].astro |
archive.php | src/pages/posts/index.astro |
page.php | src/pages/pages/[slug].astro |
category.php | src/pages/category/[slug].astro |
tag.php | src/pages/tag/[slug].astro |
search.php | src/pages/search.astro |
404.php | src/pages/404.astro |
header.php e footer.php | src/layouts/Base.astro |
template-parts/content.php | src/components/PostCard.astro ou outro componente |
O template inicial, por outro lado, usa src/pages/[slug].astro para as páginas. Escolha um único modelo de rotas e faça o urlPattern do seed e os redirecionamentos concordarem com ele.
Extraia o design
Reúna os arquivos de origem que determinam o design renderizado:
style.csse as folhas de estilo enfileiradas.theme.jsonem um tema de blocos.- A marcação dos templates e as partes de template.
- Fontes, ícones e imagens com suas licenças.
- Breakpoints responsivos e comportamento interativo.
Copie os tokens de design para o CSS do projeto Astro e construa o invólucro de documento compartilhado em src/layouts/Base.astro. Converta as partes de template repetidas em componentes antes de expandir cada rota.
Não copie os nomes de classe nem o JavaScript gerados pelo WordPress quando o novo componente não precisar do comportamento deles. Preserve o layout e a interação observáveis, não os resíduos da implementação.
Converta as consultas de arquivo
WP_Query torna-se getEmDashCollection(). Filtre e ordene na consulta para que o banco de dados faça o trabalho.
Os exemplos a seguir renderizam um arquivo dos posts mais recentes:
WordPress
<?php
$posts = new WP_Query([
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 12,
'orderby' => 'date',
'order' => 'DESC',
]);
while ($posts->have_posts()) :
$posts->the_post();
?>
<article>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
</article>
<?php endwhile; wp_reset_postdata(); ?> EmDash
---
import { getEmDashCollection } from "emdash";
const { entries: posts, error, cacheHint } = await getEmDashCollection("posts", {
orderBy: { published_at: "desc" },
limit: 12,
});
if (error) return new Response("Could not load posts", { status: 500 });
if (Astro.cache?.enabled) Astro.cache.set(cacheHint);
---
{posts.map((post) => (
<article>
<h2><a href={`/posts/${post.id}`}>{post.data.title}</a></h2>
</article>
))} Use orderBy, não sort nem sortBy. As chaves são nomes de campo armazenados, como published_at, created_at ou um campo indexado da coleção.
Converta os templates de entrada única
Use o slug de Astro.params para chamar getEmDashEntry(). Renderize o rich text com PortableText.
---
import { decodeSlug, getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";
import Base from "../../layouts/Base.astro";
const slug = decodeSlug(Astro.params.slug);
if (!slug) return Astro.rewrite("/404");
const { entry: post, error, cacheHint } = await getEmDashEntry("posts", slug);
if (error) return new Response("Could not load the post", { status: 500 });
if (!post) return Astro.rewrite("/404");
if (Astro.cache?.enabled) Astro.cache.set(cacheHint);
---
<Base title={post.data.title} content={{ collection: "posts", id: post.data.id, slug }}>
<article>
<h1 {...post.edit.title}>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>
</Base>
post.id é o identificador de rota do Astro e normalmente é o slug. post.data.id é o ID de conteúdo do EmDash armazenado. Use data.id para comentários, helpers de taxonomia e o contexto da edição visual.
Converta os arquivos de taxonomia
Resolva um termo com o nome da sua taxonomia e use esse nome no filtro where da coleção. O template de blog atual usa nomes de taxonomia e diretórios de rota no singular:
---
import { decodeSlug, getEmDashCollection, getTerm } from "emdash";
const slug = decodeSlug(Astro.params.slug);
const term = slug ? await getTerm("category", slug, { includeCounts: false }) : null;
if (!term) return Astro.rewrite("/404");
const { entries: posts } = await getEmDashCollection("posts", {
where: { category: term.slug },
orderBy: { published_at: "desc" },
});
---
<h1>{term.label}</h1>
{posts.map((post) => <a href={`/posts/${post.id}`}>{post.data.title}</a>)}
Use getTermsForEntries() com entry.data.id quando um arquivo precisar dos termos de muitas entradas. Isso agrupa a consulta de relacionamentos em lote, em vez de chamar um helper por entrada dentro de um loop.
Converta os recursos dinâmicos do tema
Menus
Crie as definições de menu em seed/seed.json e consulte-as com getMenu("primary"). Os itens de menu podem ser reordenados e editados após a configuração, então não duplique a mesma navegação como links escritos manualmente.
O componente a seguir preserva os itens de menu aninhados e marca a página atual:
---
import { getMenu } from "emdash";
const menu = await getMenu("primary");
---
{menu && (
<nav aria-label="Primary navigation">
<ul>
{menu.items.map((item) => (
<li>
<a href={item.url} aria-current={Astro.url.pathname === item.url ? "page" : undefined}>
{item.label}
</a>
{item.children.length > 0 && (
<ul>
{item.children.map((child) => (
<li><a href={child.url}>{child.label}</a></li>
))}
</ul>
)}
</li>
))}
</ul>
</nav>
)}
Áreas de widgets
Defina as áreas de widgets no seed e renderize-as com <WidgetArea name="sidebar" /> de emdash/ui. Use widgets de componente somente quando o template registrar o ID de componente correspondente.
---
import { WidgetArea } from "emdash/ui";
---
<main><slot /></main>
<aside aria-label="Related content">
<WidgetArea name="sidebar" />
</aside>
Identidade do site
Leia o título do site, o slogan, o logotipo e o favicon com getSiteSettings(). O texto jurídico ou de design estático pode permanecer no template, mas a identidade gerenciada pelo administrador deve vir das configurações.
| Valor do WordPress | Configuração do EmDash |
|---|---|
| Título do site | title |
| Slogan | tagline |
| Logotipo personalizado | logo |
| Ícone do site | favicon |
| Posts por página | postsPerPage |
Templates de página
Se os editores precisarem escolher entre vários layouts de página, adicione um campo de seleção à coleção de páginas e mapeie cada valor armazenado para um componente conhecido. Não transforme uma string armazenada em um caminho de importação arbitrário.
Shortcodes e blocos
Mapeie os shortcodes que carregam conteúdo e os blocos do WordPress para estruturas de Portable Text. Use o renderizador PortableText comum para os blocos integrados e um mapa de componentes para os valores _type personalizados.
Um seed pode fornecer dados de blocos personalizados, mas não registra um editor personalizado. Use um plugin nativo quando o port exigir renderizadores Astro empacotados ou uma interface de edição React personalizada.
Por exemplo, mapeie um shortcode de galeria do WordPress para um _type com namespace, como publication.gallery, crie um renderizador Gallery.astro e passe-o pelo mapa de componentes do PortableText:
---
import type { PortableTextBlock } from "emdash";
import { PortableText } from "emdash/ui";
import Gallery from "./blocks/Gallery.astro";
interface Props {
value: PortableTextBlock[];
}
const { value } = Astro.props;
const customTypes = { "publication.gallery": Gallery };
---
<PortableText value={value} components={{ type: customTypes }} />
Construa o seed
Nos templates atuais, o seed fica em seed/seed.json, e package.json#emdash.seed aponta para ele. Declare cada campo de coleção, taxonomia, menu, área de widgets, seção e entrada de exemplo que o template pressupõe.
O fragmento a seguir define os campos dos posts que interessam às rotas:
{
"$schema": "https://emdashcms.com/seed.schema.json",
"version": "1",
"collections": [
{
"slug": "posts",
"label": "Posts",
"labelSingular": "Post",
"supports": ["drafts", "revisions", "search", "seo"],
"urlPattern": "/posts/{slug}",
"fields": [
{ "slug": "title", "label": "Title", "type": "string", "required": true },
{ "slug": "content", "label": "Content", "type": "portableText" },
{ "slug": "excerpt", "label": "Excerpt", "type": "text" },
{ "slug": "featured_image", "label": "Featured image", "type": "image" }
]
}
]
}
Leia Arquivos seed para ver IDs de conteúdo, referências, localização, mídia, validação e opções de aplicação.
Porte em etapas verificáveis
-
Importe uma exportação representativa do WordPress e registre os blocos ou campos sem suporte.
-
Comece pelo template atual do EmDash para o destino de implantação.
-
Implemente o layout compartilhado, os tokens, a tipografia e o invólucro responsivo.
-
Implemente as rotas de arquivo e de entrada única usando os slugs e campos das coleções importadas.
-
Adicione as rotas de taxonomia, a busca, os menus, as áreas de widgets e as configurações do site que o tema de origem realmente usa.
-
Adicione definições de seed para cada dependência de rota e teste a configuração em um banco de dados vazio.
-
Compare URLs públicas representativas em larguras de celular e de desktop. Teste campos vazios, títulos longos, imagens ausentes, rascunhos e rotas 404.
-
Prepare os redirecionamentos de cada link permanente alterado antes da virada.
Lide com temas WordPress difíceis
- Temas filhos: combine a saída resolvida do tema pai e do tema filho. Porte os templates e estilos efetivos, não apenas o diretório do filho.
- Temas de blocos: use
theme.jsoncomo fonte dos tokens de design etemplates/*.htmlcomo estrutura do conteúdo, e então expresse o resultado como componentes Astro. - Construtores de páginas: importe primeiro páginas representativas. Os shortcodes e o JSON proprietário dos construtores geralmente exigem uma conversão deliberada para Portable Text ou um template de página redesenhado.
- Temas WooCommerce: trate o comportamento de comércio como uma integração de aplicação separada. Portar os arquivos de apresentação não substitui a semântica de produto, carrinho, checkout, pagamento ou pedido.