Zum Inhalt springen

Astro für WordPress-Entwickler

Astro ist ein Web-Framework zum Erstellen inhaltsorientierter Websites. Bei der Verwendung von EmDash ersetzt Astro Ihr WordPress-Theme – es übernimmt Templating, Routing und Rendering.

Dieser Leitfaden vermittelt die Grundlagen von Astro, indem er sie auf WordPress-Konzepte abbildet, die Sie bereits verstehen.

Standardmäßig serverseitig gerendert

Wie PHP läuft Astro-Code auf dem Server. Im Gegensatz zu PHP gibt es standardmäßig statisches HTML ohne JavaScript aus.

Kein JS, es sei denn, Sie fügen es hinzu

WordPress lädt jQuery und Theme-Skripte automatisch. Astro sendet nichts an den Browser, es sei denn, Sie fügen es explizit hinzu.

Komponentenbasierte Architektur

Anstelle von verstreuten Template-Tags und Includes wird mit komponierbaren, eigenständigen Komponenten gebaut.

Dateibasiertes Routing

Keine Rewrite-Regeln oder query_vars. Die Dateistruktur in src/pages/ definiert Ihre URLs direkt.

WordPress-Themes haben eine flache Struktur mit magischen Dateinamen. Astro verwendet explizite Verzeichnisse:

WordPressAstroZweck
index.php, single.phpsrc/pages/Routen (URLs)
template-parts/src/components/Wiederverwendbare UI-Teile
header.php + footer.phpsrc/layouts/Seiten-Wrapper
style.csssrc/styles/Globales CSS
functions.phpastro.config.mjsSeitenkonfiguration

Ein typisches Astro-Projekt könnte so aussehen:

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

.astro-Dateien sind das Äquivalent zu PHP-Templates in Astro. Jede Datei hat zwei Teile:

  1. Frontmatter (zwischen ----Markierungen) – Serverseitiger Code, ähnlich wie PHP am Anfang eines Templates
  2. Template – HTML mit Ausdrücken, ähnlich dem Rest eines PHP-Templates
src/components/PostCard.astro
---
// 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>

Wichtige Unterschiede zu PHP:

  • Frontmatter ist isoliert. Dort deklarierte Variablen sind im Template verfügbar, aber der Code selbst erreicht nie den Browser.
  • Imports gehören ins Frontmatter. Komponenten, Daten, Utilities – alles wird oben importiert.
  • TypeScript funktioniert. Definieren Sie Prop-Typen mit interface Props für Editor-Autovervollständigung und Validierung.

Astro-Templates verwenden {curly braces} anstelle von <?php ?>-Tags. Die Syntax ist JSX-ähnlich, gibt aber reines HTML aus.

src/components/PostList.astro
---
import { getEmDashCollection } from "emdash";
const { entries: posts } = await getEmDashCollection("posts");
const showTitle = true;
---
{showTitle && <h1>Neueste Beiträge</h1>}
{posts.length > 0 ? (
<ul>
{posts.map(post => (
<li>
<a href={`/posts/${post.id}`}>{post.data.title}</a>
</li>
))}
</ul>
) : (
<p>Keine Beiträge gefunden.</p>
)}
MusterZweck
{variable}Einen Wert ausgeben
{condition && <Element />}Bedingtes Rendering
{condition ? <A /> : <B />}If/Else
{items.map(item => <Li>{item}</Li>)}Schleifen

Komponenten empfangen Daten über Props (wie Funktionsargumente) und Slots (wie do_action-Einfügepunkte).

src/components/Card.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>

Verwendung:

<Card title="Hello" featured>
<p>Dieser Inhalt landet im Standard-Slot.</p>
<footer slot="footer">Footer-Inhalt</footer>
</Card>

In WordPress übergibt get_template_part() Daten über das $args-Array. Astro-Props sind typisiert und lassen sich direkt destrukturieren:

---
// Type-safe with defaults
interface Props {
title: string;
count?: number;
}
const { title, count = 10 } = Astro.props;
---

WordPress verwendet do_action(), um Einfügepunkte zu erstellen. Astro verwendet Slots:

WordPressAstro
do_action('before_content')<slot name="before" />
Standard-Inhaltsbereich<slot />
do_action('after_content')<slot name="after" />

Der Unterschied: Slots empfangen Kindelemente an der Aufrufstelle, während WordPress-Hooks separate add_action()-Aufrufe an anderer Stelle erfordern.

Layouts umschließen Seiten mit gemeinsamer HTML-Struktur – dem <head>, Header, Footer und allem, was seitenübergreifend geteilt wird. Dies ersetzt header.php + footer.php.

src/layouts/Base.astro
---
import "../styles/global.css";
interface Props {
title: string;
description?: string;
}
const { title, description = "Meine EmDash-Website" } = 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>

Das Layout in einer Seite verwenden:

src/pages/index.astro
---
import Base from "../../layouts/Base.astro";
---
<Base title="Startseite">
<h1>Willkommen</h1>
<p>Der Seiteninhalt wird im Slot ausgegeben.</p>
</Base>

Astro bietet mehrere Ansätze für Styling. Der charakteristischste sind scoped Styles.

Styles in einem <style>-Tag werden automatisch auf diese Komponente beschränkt:

src/components/Card.astro
<article class="card">
<h2>Titel</h2>
</article>
<style>
/* Betrifft nur .card in DIESER Komponente */
.card {
padding: 1rem;
border: 1px solid #ddd;
}
h2 {
color: navy;
}
</style>

Das generierte HTML enthält eindeutige Klassennamen, um das Auslaufen von Styles zu verhindern. Keine Spezifitätskämpfe mehr.

Für globale Styles erstellen Sie eine CSS-Datei und importieren sie in einem Layout:

src/layouts/Base.astro
---
import "../styles/global.css";
---

Die class:list-Direktive ersetzt das manuelle Zusammenbauen von Klassenzeichenketten:

---
const { featured, size = "medium" } = Astro.props;
---
<article class:list={[
"card",
size,
{ featured, "has-border": true }
]}>

Ausgabe: <article class="card medium featured has-border">

Astro liefert standardmäßig kein JavaScript aus. Dies ist die größte mentale Umstellung von WordPress.

Für einfache Interaktionen füge ein <script>-Tag hinzu:

src/components/MobileMenu.astro
<button id="menu-toggle">Menü</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>

Skripte werden automatisch gebündelt und dedupliziert. Wenn diese Komponente zweimal auf einer Seite erscheint, läuft das Skript nur einmal.

Für komplexere Interaktivität kann Astro JavaScript-Komponenten (React, Vue, Svelte) bei Bedarf laden. Dies ist optional – die meisten Websites kommen gut mit nur <script>-Tags aus.

src/pages/index.astro
---
import SearchWidget from "../../components/SearchWidget.jsx";
---
<!-- Only load JavaScript when the search box scrolls into view -->
<SearchWidget client:visible />
DirektiveWann JavaScript lädt
client:loadSofort beim Laden der Seite
client:visibleWenn Komponente in den Viewport tritt
client:idleWenn der Browser im Leerlauf ist

Astro verwendet dateibasiertes Routing. Dateien in src/pages/ werden zu URLs:

DateiURL
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].astroBeliebiger Pfad (Catch-all)

Für CMS-Inhalte verwende die Klammer-Syntax für dynamische Segmente:

src/pages/posts/[slug].astro
---
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>
WordPressAstro
Template-Hierarchie (single-post.php)Explizite Datei: posts/[slug].astro
Rewrite-Regeln + query_varsDateistruktur
$wp_query bestimmt TemplateURL weist direkt auf Datei hin
add_rewrite_rule()Dateien oder Ordner erstellen

Eine Referenz, um das Astro/EmDash-Äquivalent von WordPress-Funktionen zu finden:

WordPressAstro/EmDash
Template-HierarchieDateibasiertes Routing in src/pages/
get_template_part()Komponenten importieren und verwenden
the_content()<PortableText value={content} />
the_title(), the_*()Zugriff über post.data.title
Template-TagsTemplate-Ausdrücke {value}
body_class()class:list-Direktive
WordPressAstro/EmDash
WP_QuerygetEmDashCollection(type, filters)
get_post()getEmDashEntry(type, id)
get_posts()getEmDashCollection(type)
get_the_terms()Zugriff über entry.data.categories
get_post_meta()Zugriff über entry.data.fieldName
get_option()getSiteSettings()
wp_nav_menu()getMenu(location)
WordPressAstro/EmDash
add_action()EmDash-Hooks, Astro-Middleware
add_filter()EmDash-Hooks
add_shortcode()Portable Text benutzerdefinierte Blöcke
register_block_type()Portable Text benutzerdefinierte Blöcke
register_sidebar()EmDash-Widget-Bereiche
PluginsAstro-Integrationen + EmDash-Plugins
WordPressAstro/EmDash
register_post_type()Sammlung in Admin-Oberfläche erstellen
register_taxonomy()Taxonomie in Admin-Oberfläche erstellen
register_meta()Feld zum Sammlungsschema hinzufügen
BeitragsstatusEintragsstatus (Entwurf, veröffentlicht, etc.)
BeitragsbildMedien-Referenzfeld
Gutenberg-BlöckePortable Text-Blöcke

Der Sprung von WordPress zu Astro ist bedeutend, aber logisch:

  1. PHP-Vorlagen → Astro-Komponenten — Gleiches Prinzip (Servercode + HTML), bessere Organisation
  2. Template-Tags → Props und Imports — Expliziter Datenfluss statt globaler Variablen
  3. Theme-Dateien → Seitenverzeichnis — URLs entsprechen der Dateistruktur
  4. Hooks → Slots und Middleware — Vorhersehbarere Einfügepunkte
  5. Standardmäßig jQuery → Standardmäßig kein JS — Interaktivität gezielt hinzufügen

Beginnen Sie mit dem Erste-Schritte-Leitfaden, um Ihre erste EmDash-Website zu erstellen, oder erkunden Sie Arbeiten mit Inhalten, um zu lernen, wie Sie CMS-Daten abfragen und darstellen können.