Astro è un framework web per la creazione di siti web orientati ai contenuti. Quando si utilizza EmDash, Astro sostituisce il tuo tema WordPress: gestisce il templating, il routing e il rendering.
Questa guida insegna i fondamenti di Astro mappandoli sui concetti WordPress che già comprendi.
Cambiamenti di paradigma chiave
Renderizzato lato server per impostazione predefinita
Come PHP, il codice Astro viene eseguito sul server. A differenza di PHP, genera HTML statico per impostazione predefinita con zero JavaScript.
Zero JS a meno che non lo aggiungi
WordPress carica jQuery e gli script del tema automaticamente. Astro non invia nulla al browser a meno che non lo aggiungi esplicitamente.
Architettura basata su componenti
Invece di tag di template sparsi e include, costruisci con componenti componibili e autonomi.
Routing basato su file
Nessuna regola di riscrittura o query_vars. La struttura dei file in src/pages/ definisce i tuoi URL direttamente.
Struttura del progetto
I temi WordPress hanno una struttura piatta con nomi di file magici. Astro utilizza directory esplicite:
| WordPress | Astro | Scopo |
|---|---|---|
index.php, single.php | src/pages/ | Routes (URLs) |
template-parts/ | src/components/ | Pezzi di UI riutilizzabili |
header.php + footer.php | src/layouts/ | Wrapper di pagina |
style.css | src/styles/ | CSS globale |
functions.php | astro.config.mjs | Configurazione del sito |
L’albero seguente mostra un layout tipico di progetto 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
Componenti Astro
I file .astro sono l’equivalente Astro dei template PHP. Ogni file ha due parti:
- Frontmatter (tra i delimitatori
---) — Codice lato server, come PHP all’inizio di un template - Template — HTML con espressioni, come il resto di un template PHP
Il seguente componente dichiara props tipizzate nel frontmatter e le renderizza nel 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>
Differenze chiave da PHP:
- Il frontmatter è isolato. Le variabili dichiarate lì sono disponibili nel template, ma il codice stesso non raggiunge mai il browser.
- Gli import vanno nel frontmatter. Componenti, dati, utility: tutto viene importato in alto.
- TypeScript funziona. Definisci i tipi di props con
interface Propsper l’autocompletamento dell’editor e la validazione.
Espressioni di template
I template Astro usano {parentesi graffe} invece dei tag <?php ?>. La sintassi è simile a JSX ma genera HTML puro.
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; ?> Pattern di espressione
| Pattern | Scopo |
|---|---|
{variable} | Mostra un valore |
{condition && <Element />} | Rendering condizionale |
{condition ? <A /> : <B />} | If/else |
{items.map(item => <Li>{item}</Li>)} | Loop |
Props e Slots
I componenti ricevono dati tramite props (come argomenti di funzione) e slots (come punti di inserimento 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>Il seguente markup utilizza quel componente, passando lo slot predefinito e uno slot footer nominato:
<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
In WordPress, get_template_part() passa i dati tramite l’array $args. Le props Astro sono tipizzate e destrutturate:
---
// Type-safe with defaults
interface Props {
title: string;
count?: number;
}
const { title, count = 10 } = Astro.props;
---
Slots vs Hooks
WordPress utilizza do_action() per creare punti di inserimento. Astro utilizza gli slot:
| WordPress | Astro |
|---|---|
do_action('before_content') | <slot name="before" /> |
| Area contenuti predefinita | <slot /> |
do_action('after_content') | <slot name="after" /> |
La differenza: gli slot ricevono elementi figli nel sito di chiamata, mentre gli hook di WordPress richiedono chiamate add_action() separate altrove.
Layout
I layout avvolgono le pagine con una struttura HTML comune: il <head>, header, footer e tutto ciò che è condiviso tra le pagine. Questo sostituisce header.php + footer.php. Il seguente layout definisce quella shell condivisa ed espone uno slot per il contenuto della pagina:
---
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>
Utilizza il layout in una pagina:
---
import Base from "../layouts/Base.astro";
---
<Base title="Home">
<h1>Welcome</h1>
<p>Page content goes in the slot.</p>
</Base>
Stili
Astro offre diversi approcci di stilizzazione. Il più distintivo sono gli stili con ambito.
Stili con ambito
Gli stili in un tag <style> sono automaticamente limitati a quel componente:
<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>
L’HTML generato include nomi di classe univoci per prevenire la fuoriuscita di stili, in modo che gli stili dei componenti rimangano contenuti senza aumentare la specificità del selettore.
Stili globali
Per stili a livello di sito, crea un file CSS e importalo in un layout:
---
import "../styles/global.css";
---
Classi condizionali
La direttiva class:list sostituisce la costruzione manuale di stringhe di classe:
Astro
---
const { featured, size = "medium" } = Astro.props;
---
<article class:list={[
"card",
size,
{ featured, "has-border": true }
]}>Output: <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 lato client
Astro invia zero JavaScript per impostazione predefinita. Questo è il più grande cambiamento mentale da WordPress.
Aggiungere interattività
Per interazioni semplici, aggiungi un tag <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>
Gli script vengono automaticamente raggruppati e deduplicati. Se questo componente appare due volte su una pagina, lo script viene eseguito una volta.
Componenti interattivi avanzati
Per un’interattività più complessa, Astro può caricare componenti JavaScript (React, Vue, Svelte) su richiesta. Questo è opzionale: la maggior parte dei siti funziona bene con solo tag <script>. La seguente pagina carica un componente solo quando scorre nella vista:
---
import SearchWidget from "../components/SearchWidget.jsx";
---
<!-- Only load JavaScript when the search box scrolls into view -->
<SearchWidget client:visible />
| Direttiva | Quando si carica JavaScript |
|---|---|
client:load | Immediatamente al caricamento della pagina |
client:visible | Quando il componente entra nel viewport |
client:idle | Quando il browser è inattivo |
Routing
Astro utilizza il routing basato su file. I file in src/pages/ diventano URL:
| File | 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 | Qualsiasi percorso (catch-all) |
Route dinamiche
Per contenuti CMS, utilizza la sintassi con parentesi per segmenti dinamici:
---
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>
Confronto con WordPress
| WordPress | Astro |
|---|---|
Gerarchia di template (single-post.php) | File esplicito: posts/[slug].astro |
Regole di riscrittura + query_vars | Struttura dei file |
$wp_query determina il template | URL mappa direttamente al file |
add_rewrite_rule() | Creare file o cartelle |
Dove vivono i concetti WordPress
Un riferimento per trovare l’equivalente Astro/EmDash delle funzionalità WordPress:
Templating
| WordPress | Astro/EmDash |
|---|---|
| Gerarchia di template | Routing basato su file in src/pages/ |
get_template_part() | Importare e utilizzare componenti |
the_content() | <PortableText value={content} /> |
the_title(), the_*() | Accesso tramite post.data.title |
| Tag di template | Espressioni di template {value} |
body_class() | Direttiva class:list |
Dati e query
| WordPress | Astro/EmDash |
|---|---|
WP_Query | getEmDashCollection(type, filters) |
get_post() | getEmDashEntry(type, id) |
get_posts() | getEmDashCollection(type) |
get_the_terms() | Accesso tramite entry.data.categories |
get_post_meta() | Accesso tramite entry.data.fieldName |
get_option() | getSiteSettings() |
wp_nav_menu() | getMenu(location) |
Estensibilità
| WordPress | Astro/EmDash |
|---|---|
add_action() | Hook EmDash, middleware Astro |
add_filter() | Hook EmDash |
add_shortcode() | Blocchi personalizzati Portable Text |
register_block_type() | Blocchi personalizzati Portable Text |
register_sidebar() | Aree widget EmDash |
| Plugin | Integrazioni Astro + plugin EmDash |
Tipi di contenuto
| WordPress | Astro/EmDash |
|---|---|
register_post_type() | Creare collezione nell’UI admin |
register_taxonomy() | Creare tassonomia nell’UI admin |
register_meta() | Aggiungere campo allo schema di collezione |
| Stato post | Stato voce (draft, published, etc.) |
| Immagine in evidenza | Campo di riferimento media |
| Blocchi Gutenberg | Blocchi Portable Text |
Mappatura dei concetti
I principali cambiamenti da WordPress ad Astro trattati in questa guida:
- I template PHP diventano componenti Astro: codice server più HTML, con organizzazione file esplicita.
- I tag di template diventano props e import: i dati fluiscono attraverso argomenti invece di globali.
- I file del tema diventano una directory di pagine: gli URL corrispondono alla struttura dei file.
- Gli hook diventano slot e middleware: i punti di inserimento sono definiti dove viene passato il contenuto.
- jQuery si carica per impostazione predefinita in WordPress; Astro non invia JavaScript finché non lo aggiungi.
Inizia con la guida Getting Started per creare il tuo primo sito EmDash, o esplora Working with Content per imparare a interrogare e renderizzare dati CMS.