Portez un thème WordPress en séparant son design, ses modèles de route et les fonctionnalités gérées par la base de données. Le résultat est un projet Astro complet avec des requêtes EmDash et un fichier seed, et non un thème PHP chargé par un runtime de thèmes.
Commencer par le contenu et les URL
Importez un contenu représentatif avant de convertir les modèles. Notez les types de contenu WordPress, les taxonomies, les règles de permaliens, les menus, les zones de widgets, les valeurs du Customizer, les shortcodes et le balisage généré par les plugins qu’utilise le site.
Choisissez la nouvelle URL de chaque type de contenu. Les routes Astro sont des fichiers explicites : il n’existe donc pas d’équivalent automatique de la hiérarchie des modèles de WordPress.
Le modèle de blog actuel utilise cette correspondance :
| WordPress | Chemin du modèle 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 et footer.php | src/layouts/Base.astro |
template-parts/content.php | src/components/PostCard.astro ou un autre composant |
Le modèle de démarrage utilise en revanche src/pages/[slug].astro pour les pages. Choisissez un modèle de routes et faites en sorte que le urlPattern du seed et les redirections soient cohérents avec lui.
Extraire le design
Rassemblez les fichiers source qui déterminent le design rendu :
style.csset les feuilles de style mises en file d’attente.theme.jsonpour un thème de blocs.- Le balisage des modèles et les parties de modèle.
- Les polices, les icônes et les images, avec leurs licences.
- Les points de rupture responsives et les comportements interactifs.
Copiez les jetons de design dans le CSS du projet Astro et construisez l’enveloppe de document partagée dans src/layouts/Base.astro. Convertissez en composants les parties de modèle répétées avant de développer chaque route.
Ne copiez pas les noms de classe ni le JavaScript générés par WordPress lorsque le nouveau composant n’a pas besoin de leur comportement. Conservez la mise en page et l’interaction observables, pas les résidus de l’implémentation.
Convertir les requêtes d’archive
WP_Query devient getEmDashCollection(). Filtrez et triez dans la requête afin que la base de données fasse le travail.
Les exemples suivants affichent une archive des derniers articles :
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>
))} Utilisez orderBy, et non sort ou sortBy. Les clés sont des noms de champ stockés, tels que published_at, created_at, ou un champ de collection indexé.
Convertir les modèles d’entrée unique
Utilisez le slug provenant de Astro.params pour appeler getEmDashEntry(). Affichez le texte enrichi avec 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 est l’identifiant de route d’Astro et correspond normalement au slug. post.data.id est l’ID de contenu EmDash stocké. Utilisez data.id pour les commentaires, les assistants de taxonomie et le contexte de l’édition visuelle.
Convertir les archives de taxonomie
Résolvez un terme avec le nom de sa taxonomie, puis utilisez ce nom dans le filtre where de la collection. Le modèle de blog actuel utilise des noms de taxonomie et des répertoires de route au singulier :
---
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>)}
Utilisez getTermsForEntries() avec entry.data.id lorsqu’une archive a besoin des termes de nombreuses entrées. La requête de relation est alors traitée par lots, au lieu d’appeler un assistant par entrée dans une boucle.
Convertir les fonctionnalités dynamiques du thème
Menus
Créez les définitions de menu dans seed/seed.json et interrogez-les avec getMenu("primary"). Les éléments de menu peuvent être réordonnés et modifiés après la configuration ; ne dupliquez donc pas la même navigation sous forme de liens codés en dur.
Le composant suivant conserve les éléments de menu imbriqués et signale la page courante :
---
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>
)}
Zones de widgets
Définissez les zones de widgets dans le seed et affichez-les avec <WidgetArea name="sidebar" /> depuis emdash/ui. N’utilisez des widgets de composant que si le modèle enregistre l’ID de composant correspondant.
---
import { WidgetArea } from "emdash/ui";
---
<main><slot /></main>
<aside aria-label="Related content">
<WidgetArea name="sidebar" />
</aside>
Identité du site
Lisez le titre du site, le slogan, le logo et le favicon avec getSiteSettings(). Les textes juridiques ou de design statiques peuvent rester dans le modèle, mais l’identité gérée par l’administrateur doit provenir des paramètres.
| Valeur WordPress | Paramètre EmDash |
|---|---|
| Titre du site | title |
| Slogan | tagline |
| Logo personnalisé | logo |
| Icône du site | favicon |
| Articles par page | postsPerPage |
Modèles de page
Si les éditeurs doivent choisir parmi plusieurs mises en page, ajoutez un champ de sélection à la collection de pages et associez chaque valeur stockée à un composant connu. Ne transformez pas une chaîne stockée en chemin d’import arbitraire.
Shortcodes et blocs
Associez les shortcodes porteurs de contenu et les blocs WordPress à des structures Portable Text. Utilisez le moteur de rendu PortableText ordinaire pour les blocs intégrés et une table de composants pour les valeurs _type personnalisées.
Un seed peut fournir des données de bloc personnalisées, mais il n’enregistre pas d’éditeur personnalisé. Utilisez un plugin natif lorsque le portage requiert des moteurs de rendu Astro packagés ou une interface d’édition React personnalisée.
Par exemple, associez un shortcode de galerie WordPress à un _type avec espace de noms, tel que publication.gallery, créez un moteur de rendu Gallery.astro et transmettez-le via la table de composants de 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 }} />
Construire le seed
Dans les modèles actuels, le seed se trouve dans seed/seed.json, et package.json#emdash.seed y pointe. Déclarez chaque champ de collection, taxonomie, menu, zone de widgets, section et entrée d’exemple que le modèle suppose présents.
Le fragment suivant définit les champs des articles qui interviennent dans les routes :
{
"$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" }
]
}
]
}
Lisez Fichiers seed pour les ID de contenu, les références, la localisation, les médias, la validation et les options d’application.
Porter par étapes vérifiables
-
Importez un export WordPress représentatif et notez les blocs ou champs non pris en charge.
-
Partez du modèle EmDash actuel correspondant à la cible de déploiement.
-
Implémentez la mise en page partagée, les jetons, la typographie et l’enveloppe responsive.
-
Implémentez les routes d’archive et d’entrée unique en utilisant les slugs et les champs des collections importées.
-
Ajoutez les routes de taxonomie, la recherche, les menus, les zones de widgets et les paramètres du site que le thème source utilise réellement.
-
Ajoutez des définitions seed pour chaque dépendance de route et testez la configuration sur une base de données vide.
-
Comparez des URL publiques représentatives en largeur mobile et bureau. Testez les champs vides, les titres longs, les images manquantes, les brouillons et les routes 404.
-
Préparez les redirections de chaque permalien modifié avant la bascule.
Gérer les thèmes WordPress difficiles
- Thèmes enfants : combinez la sortie résolue du thème parent et du thème enfant. Portez les modèles et les styles effectifs, et pas seulement le répertoire du thème enfant.
- Thèmes de blocs : utilisez
theme.jsoncomme source des jetons de design ettemplates/*.htmlcomme structure du contenu, puis exprimez le résultat sous forme de composants Astro. - Constructeurs de pages : importez d’abord des pages représentatives. Les shortcodes et le JSON propriétaire des constructeurs exigent généralement une conversion réfléchie vers Portable Text ou un modèle de page repensé.
- Thèmes WooCommerce : traitez le comportement e-commerce comme une intégration applicative distincte. Porter les fichiers de présentation ne remplace pas la sémantique des produits, du panier, du paiement, du règlement ou des commandes.