Astro est un framework web pour créer des sites web axés sur le contenu. Lors de l’utilisation d’EmDash, Astro remplace votre thème WordPress — il gère le templating, le routage et le rendu.
Ce guide enseigne les fondamentaux d’Astro en les associant aux concepts WordPress que vous comprenez déjà.
Changements de paradigme clés
Rendu côté serveur par défaut
Comme PHP, le code Astro s’exécute sur le serveur. Contrairement à PHP, il génère du HTML statique par défaut avec zéro JavaScript.
Zéro JS sauf si vous l'ajoutez
WordPress charge jQuery et les scripts de thème automatiquement. Astro ne livre rien au navigateur sauf si vous l’ajoutez explicitement.
Architecture basée sur les composants
Au lieu de balises de template dispersées et d’includes, construisez avec des composants composables et autonomes.
Routage basé sur les fichiers
Pas de règles de réécriture ou de query_vars. La structure de fichiers dans src/pages/ définit vos URLs directement.
Structure du projet
Les thèmes WordPress ont une structure plate avec des noms de fichiers magiques. Astro utilise des répertoires explicites :
| WordPress | Astro | Objectif |
|---|---|---|
index.php, single.php | src/pages/ | Routes (URLs) |
template-parts/ | src/components/ | Éléments d’UI réutilisables |
header.php + footer.php | src/layouts/ | Enveloppes de page |
style.css | src/styles/ | CSS global |
functions.php | astro.config.mjs | Configuration du site |
L’arborescence suivante montre une disposition typique de projet Astro :
src/
├── components/ # Reusable UI (Header, PostCard, etc.)
├── layouts/ # Page shells (Base.astro)
├── pages/ # Routes - files become URLs
│ ├── index.astro # → /
│ ├── posts/
│ │ ├── index.astro # → /posts
│ │ └── [slug].astro # → /posts/hello-world
│ └── [slug].astro # → /about, /contact, etc.
└── styles/
└── global.css
Composants Astro
Les fichiers .astro sont l’équivalent Astro des templates PHP. Chaque fichier comporte deux parties :
- Frontmatter (entre les délimiteurs
---) — Code côté serveur, comme PHP en haut d’un template - Template — HTML avec expressions, comme le reste d’un template PHP
Le composant suivant déclare des props typés dans le frontmatter et les rend dans le template :
---
// Frontmatter: runs on server, never sent to browser
interface Props {
title: string;
excerpt: string;
url: string;
}
const { title, excerpt, url } = Astro.props;
---
<!-- Template: outputs HTML -->
<article class="post-card">
<h2><a href={url}>{title}</a></h2>
<p>{excerpt}</p>
</article>
Différences clés avec PHP :
- Le frontmatter est isolé. Les variables déclarées là sont disponibles dans le template, mais le code lui-même n’atteint jamais le navigateur.
- Les imports vont dans le frontmatter. Composants, données, utilitaires — tout est importé en haut.
- TypeScript fonctionne. Définissez les types de props avec
interface Propspour l’autocomplétion de l’éditeur et la validation.
Expressions de template
Les templates Astro utilisent des {accolades} au lieu de balises <?php ?>. La syntaxe est similaire à JSX mais génère du HTML pur.
Astro
---
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts");
const showTitle = true;
---
{showTitle && <h1>Latest Posts</h1>}
{posts.length > 0 ? (
<ul>
{posts.map(post => (
<li>
<a href={`/posts/${post.id}`}>{post.data.title}</a>
</li>
))}
</ul>
) : (
<p>No posts found.</p>
)} PHP
<?php
$posts = new WP_Query(['post_type' => 'post']);
$show_title = true;
?>
<?php if ($show_title): ?>
<h1>Latest Posts</h1>
<?php endif; ?>
<?php if ($posts->have_posts()): ?>
<ul>
<?php while ($posts->have_posts()): $posts->the_post(); ?>
<li>
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</li>
<?php endwhile; wp_reset_postdata(); ?>
</ul>
<?php else: ?>
<p>No posts found.</p>
<?php endif; ?> Modèles d’expression
| Modèle | Objectif |
|---|---|
{variable} | Afficher une valeur |
{condition && <Element />} | Rendu conditionnel |
{condition ? <A /> : <B />} | If/else |
{items.map(item => <Li>{item}</Li>)} | Boucles |
Props et Slots
Les composants reçoivent des données via des props (comme des arguments de fonction) et des slots (comme des points d’insertion do_action).
Astro
---
interface Props {
title: string;
featured?: boolean;
}
const { title, featured = false } = Astro.props;
---
<article class:list={["card", { featured }]}>
<h2>{title}</h2>
<slot />
<slot name="footer" />
</article>Le balisage suivant utilise ce composant, en passant le slot par défaut et un slot footer nommé :
<Card title="Hello" featured>
<p>This goes in the default slot.</p>
<footer slot="footer">Footer content</footer>
</Card> PHP
<?php
// Usage: get_template_part('template-parts/card', null, [
// 'title' => 'Hello',
// 'featured' => true
// ]);
$title = $args['title'] ?? '';
$featured = $args['featured'] ?? false;
$class = $featured ? 'card featured' : 'card';
?>
<article class="<?php echo esc_attr($class); ?>">
<h2><?php echo esc_html($title); ?></h2>
<?php
// No direct equivalent to slots.
// WordPress uses do_action() for similar patterns:
do_action('card_content');
do_action('card_footer');
?>
</article> Props vs $args
Dans WordPress, get_template_part() passe les données via le tableau $args. Les props Astro sont typés et déstructurés :
---
// Type-safe with defaults
interface Props {
title: string;
count?: number;
}
const { title, count = 10 } = Astro.props;
---
Slots vs Hooks
WordPress utilise do_action() pour créer des points d’insertion. Astro utilise des slots :
| WordPress | Astro |
|---|---|
do_action('before_content') | <slot name="before" /> |
| Zone de contenu par défaut | <slot /> |
do_action('after_content') | <slot name="after" /> |
La différence : les slots reçoivent des éléments enfants sur le site d’appel, tandis que les hooks WordPress nécessitent des appels add_action() séparés ailleurs.
Layouts
Les layouts enveloppent les pages avec une structure HTML commune — le <head>, l’en-tête, le pied de page et tout ce qui est partagé entre les pages. Cela remplace header.php + footer.php. Le layout suivant définit cette enveloppe partagée et expose un slot pour le contenu de la page :
---
import "../styles/global.css";
interface Props {
title: string;
description?: string;
}
const { title, description = "My EmDash Site" } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content={description} />
<title>{title}</title>
</head>
<body>
<header>
<nav><!-- Navigation --></nav>
</header>
<main>
<slot />
</main>
<footer>
<p>© {new Date().getFullYear()}</p>
</footer>
</body>
</html>
Utilisez le layout dans une page :
---
import Base from "../layouts/Base.astro";
---
<Base title="Home">
<h1>Welcome</h1>
<p>Page content goes in the slot.</p>
</Base>
Stylisation
Astro offre plusieurs approches de stylisation. La plus distinctive sont les styles scopés.
Styles scopés
Les styles dans une balise <style> sont automatiquement scopés à ce composant :
<article class="card">
<h2>Title</h2>
</article>
<style>
/* Only affects .card in THIS component */
.card {
padding: 1rem;
border: 1px solid #ddd;
}
h2 {
color: navy;
}
</style>
Le HTML généré inclut des noms de classe uniques pour empêcher la fuite de styles, de sorte que les styles des composants restent contenus sans escalader la spécificité du sélecteur.
Styles globaux
Pour les styles à l’échelle du site, créez un fichier CSS et importez-le dans un layout :
---
import "../styles/global.css";
---
Classes conditionnelles
La directive class:list remplace la construction manuelle de chaînes de classe :
Astro
---
const { featured, size = "medium" } = Astro.props;
---
<article class:list={[
"card",
size,
{ featured, "has-border": true }
]}>Sortie : <article class="card medium featured has-border">
PHP
<?php
$classes = ['card', $size];
if ($featured) $classes[] = 'featured';
if (true) $classes[] = 'has-border';
?>
<article class="<?php echo esc_attr(implode(' ', $classes)); ?>"> JavaScript côté client
Astro livre zéro JavaScript par défaut. C’est le plus grand changement mental par rapport à WordPress.
Ajout d’interactivité
Pour des interactions simples, ajoutez une balise <script> :
<button id="menu-toggle">Menu</button>
<nav id="mobile-menu" hidden>
<slot />
</nav>
<script>
const toggle = document.getElementById("menu-toggle");
const menu = document.getElementById("mobile-menu");
toggle?.addEventListener("click", () => {
menu?.toggleAttribute("hidden");
});
</script>
Les scripts sont automatiquement regroupés et dédupliqués. Si ce composant apparaît deux fois sur une page, le script s’exécute une fois.
Composants interactifs avancés
Pour une interactivité plus complexe, Astro peut charger des composants JavaScript (React, Vue, Svelte) à la demande. C’est optionnel — la plupart des sites fonctionnent bien avec juste des balises <script>. La page suivante charge un composant uniquement lorsqu’il défile dans la vue :
---
import SearchWidget from "../components/SearchWidget.jsx";
---
<!-- Only load JavaScript when the search box scrolls into view -->
<SearchWidget client:visible />
| Directive | Quand JavaScript se charge |
|---|---|
client:load | Immédiatement au chargement de la page |
client:visible | Quand le composant entre dans le viewport |
client:idle | Quand le navigateur est inactif |
Routage
Astro utilise le routage basé sur les fichiers. Les fichiers dans src/pages/ deviennent des URLs :
| Fichier | URL |
|---|---|
src/pages/index.astro | / |
src/pages/about.astro | /about |
src/pages/posts/index.astro | /posts |
src/pages/posts/[slug].astro | /posts/hello-world |
src/pages/[...slug].astro | Tout chemin (catch-all) |
Routes dynamiques
Pour le contenu CMS, utilisez la syntaxe entre crochets pour les segments dynamiques :
---
import { getEmDashCollection, getEmDashEntry } from "emdash";
import Base from "../../layouts/Base.astro";
import { PortableText } from "emdash/ui";
// For static builds, define which pages to generate
export async function getStaticPaths() {
const { entries: posts } = await getEmDashCollection("posts");
return posts.map(post => ({
params: { slug: post.id },
props: { post },
}));
}
const { post } = Astro.props;
---
<Base title={post.data.title}>
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>
</Base>
Comparé à WordPress
| WordPress | Astro |
|---|---|
Hiérarchie de templates (single-post.php) | Fichier explicite : posts/[slug].astro |
Règles de réécriture + query_vars | Structure de fichiers |
$wp_query détermine le template | URL mappe directement au fichier |
add_rewrite_rule() | Créer des fichiers ou des dossiers |
Où vivent les concepts WordPress
Une référence pour trouver l’équivalent Astro/EmDash des fonctionnalités WordPress :
Templating
| WordPress | Astro/EmDash |
|---|---|
| Hiérarchie de templates | Routage basé sur les fichiers dans src/pages/ |
get_template_part() | Importer et utiliser des composants |
the_content() | <PortableText value={content} /> |
the_title(), the_*() | Accès via post.data.title |
| Balises de template | Expressions de template {value} |
body_class() | Directive class:list |
Données et requêtes
| WordPress | Astro/EmDash |
|---|---|
WP_Query | getEmDashCollection(type, filters) |
get_post() | getEmDashEntry(type, id) |
get_posts() | getEmDashCollection(type) |
get_the_terms() | Accès via entry.data.categories |
get_post_meta() | Accès via entry.data.fieldName |
get_option() | getSiteSettings() |
wp_nav_menu() | getMenu(location) |
Extensibilité
| WordPress | Astro/EmDash |
|---|---|
add_action() | Hooks EmDash, middleware Astro |
add_filter() | Hooks EmDash |
add_shortcode() | Blocs personnalisés Portable Text |
register_block_type() | Blocs personnalisés Portable Text |
register_sidebar() | Zones de widgets EmDash |
| Plugins | Intégrations Astro + plugins EmDash |
Types de contenu
| WordPress | Astro/EmDash |
|---|---|
register_post_type() | Créer une collection dans l’UI admin |
register_taxonomy() | Créer une taxonomie dans l’UI admin |
register_meta() | Ajouter un champ au schéma de collection |
| Statut de post | Statut d’entrée (draft, published, etc.) |
| Image mise en avant | Champ de référence média |
| Blocs Gutenberg | Blocs Portable Text |
Mappage des concepts
Les principaux changements de WordPress à Astro couverts dans ce guide :
- Les templates PHP deviennent des composants Astro : code serveur plus HTML, avec une organisation de fichiers explicite.
- Les balises de template deviennent des props et des imports : les données transitent par des arguments plutôt que par des globales.
- Les fichiers de thème deviennent un répertoire de pages : les URLs correspondent à la structure de fichiers.
- Les hooks deviennent des slots et du middleware : les points d’insertion sont définis là où le contenu est passé.
- jQuery se charge par défaut dans WordPress ; Astro ne livre pas de JavaScript tant que vous ne l’ajoutez pas.
Commencez avec le guide Getting Started pour créer votre premier site EmDash, ou explorez Working with Content pour apprendre à interroger et rendre des données CMS.