Astro per sviluppatori WordPress

In questa pagina

Astro è un framework web per siti incentrati sul contenuto. Con EmDash, Astro sostituisce il tema WordPress—gestisce templating, routing e rendering.

Questa guida insegna le basi di Astro mappandole sui concetti WordPress che già capisci.

Cambi di paradigma chiave

Renderizzato sul server di default

Come PHP, il codice Astro gira sul server. A differenza di PHP, di default produce HTML statico con zero JavaScript.

Zero JS se non lo aggiungi

WordPress carica jQuery e gli script del tema automaticamente. Astro non invia nulla al browser a meno che tu non lo aggiunga esplicitamente.

Architettura a componenti

Invece di tag template e include sparsi, costruisci con componenti componibili e autocontenuti.

Routing basato su file

Niente regole di rewrite o query_vars. La struttura dei file in src/pages/ definisce direttamente gli URL.

Struttura del progetto

I temi WordPress hanno una struttura piatta con nomi file «magici». Astro usa directory esplicite:

WordPressAstroScopo
index.php, single.phpsrc/pages/Route (URL)
template-parts/src/components/Pezzi UI riutilizzabili
header.php + footer.phpsrc/layouts/Involucri di pagina
style.csssrc/styles/CSS globale
functions.phpastro.config.mjsConfigurazione del sito

Un tipico 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:

  1. Frontmatter (tra le barre ---) — Codice lato server, come il PHP in cima a un template
  2. Template — HTML con espressioni, come il resto di un template PHP
---
// 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 rispetto a PHP:

  • Il frontmatter è isolato. Le variabili dichiarate lì sono disponibili nel template, ma il codice non arriva mai al browser.
  • Gli import vanno nel frontmatter. Componenti, dati, utility—tutto importato in cima.
  • TypeScript funziona. Definisci i tipi delle props con interface Props per autocomplete e validazione nell’editor.

Espressioni template

I template Astro usano {graffe} al posto dei tag <?php ?>. La sintassi è simile a JSX ma produce 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

PatternScopo
{variable}Emissione di un valore
{condition && <Element />}Rendering condizionale
{condition ? <A /> : <B />}If/else
{items.map(item => <Li>{item}</Li>)}Cicli

Props e slot

I componenti ricevono dati tramite props (come argomenti di funzione) e slot (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>

Uso:

<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 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;
---

Slot vs hook

WordPress usa do_action() per creare punti di inserimento. Astro usa gli slot:

WordPressAstro
do_action('before_content')<slot name="before" />
Default content area<slot />
do_action('after_content')<slot name="after" />

La differenza: gli slot ricevono elementi figli nel punto di chiamata, mentre gli hook WordPress richiedono chiamate add_action() separate altrove.

Layout

I layout avvolgono le pagine con HTML comune—<head>, header, footer e tutto ciò che è condiviso. Sostituiscono header.php + footer.php.

---
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>&copy; {new Date().getFullYear()}</p>
    </footer>
  </body>
</html>

Usare 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>

Styling

Astro offre diversi approcci allo stile. Il più distintivo è lo scoped style.

Scoped styles

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 unici per evitare leakage di stile. Basta guerre di specificità.

Stili globali

Per stili su tutto il 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 classi:

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 non invia JavaScript di default. Questo è il salto mentale più grande rispetto a 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 sono raggruppati e deduplicati automaticamente. Se il componente compare due volte nella pagina, lo script gira una volta.

Avanzato: componenti interattivi

Per interattività più complessa, Astro può caricare componenti JavaScript (React, Vue, Svelte) on demand. È opzionale—molti siti vanno bene solo con <script>.

---
import SearchWidget from "../components/SearchWidget.jsx";
---
<!-- Only load JavaScript when the search box scrolls into view -->
<SearchWidget client:visible />
DirectiveQuando si carica JavaScript
client:loadSubito al caricamento della pagina
client:visibleQuando il componente entra nel viewport
client:idleQuando il browser è in idle

Routing

Astro usa il routing basato su file. I file in src/pages/ diventano URL:

FileURL
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].astroAny path (catch-all)

Route dinamiche

Per contenuti CMS, usa la sintassi con parentesi quadre per i 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>

Rispetto a WordPress

WordPressAstro
Template hierarchy (single-post.php)Explicit file: posts/[slug].astro
Rewrite rules + query_varsFile structure
$wp_query determines templateURL maps directly to file
add_rewrite_rule()Create files or folders

Dove vivono i concetti WordPress

Riferimento per trovare l’equivalente Astro/EmDash delle funzionalità WordPress:

Templating

WordPressAstro/EmDash
Template hierarchyFile-based routing in src/pages/
get_template_part()Import and use components
the_content()<PortableText value={content} />
the_title(), the_*()Access via post.data.title
Template tagsTemplate expressions {value}
body_class()class:list directive

Dati e query

WordPressAstro/EmDash
WP_QuerygetEmDashCollection(type, filters)
get_post()getEmDashEntry(type, id)
get_posts()getEmDashCollection(type)
get_the_terms()Access via entry.data.categories
get_post_meta()Access via entry.data.fieldName
get_option()getSiteSettings()
wp_nav_menu()getMenu(location)

Estensibilità

WordPressAstro/EmDash
add_action()EmDash hooks, Astro middleware
add_filter()EmDash hooks
add_shortcode()Portable Text custom blocks
register_block_type()Portable Text custom blocks
register_sidebar()EmDash widget areas
PluginsAstro integrations + EmDash plugins

Tipi di contenuto

WordPressAstro/EmDash
register_post_type()Create collection in admin UI
register_taxonomy()Create taxonomy in admin UI
register_meta()Add field to collection schema
Post statusEntry status (draft, published, etc.)
Featured imageMedia reference field
Gutenberg blocksPortable Text blocks

Il passaggio da WordPress ad Astro è significativo ma logico:

  1. Template PHP → componenti Astro — Stessa idea (codice server + HTML), organizzazione migliore
  2. Tag template → props e import — Flusso dati esplicito invece di globali
  3. File del tema → directory pages — Gli URL seguono la struttura dei file
  4. Hook → slot e middleware — Punti di inserimento più prevedibili
  5. jQuery di default → zero JS di default — Aggiungi interattività in modo intenzionale

Inizia dalla guida Getting Started per il tuo primo sito EmDash, o esplora Working with Content per interrogare e renderizzare i dati del CMS.