Communitygithub.com

sijad/astro-wordpress

Verwandle ein statisches Astro-Template in ein WordPress-Theme mit dem astro-wordpress-Adapter – Installation des Adapters, Konfiguration der astro.config.mjs, Hinzufügen des Theme-style.css und Konvertierung von Seiten zu .php.astro. Optional kann WordPress selbst mit Docker Compose betrieben werden.

Was ist astro-wordpress?

Diese Fähigkeit wandelt ein statisches Astro-Projekt in ein vollwertiges WordPress-Theme um, indem sie den astro-wordpress-Adapter installiert und konfiguriert. Sie ist ideal für Entwickler, die bestehende Astro-Seiten in WordPress integrieren möchten, ohne das gesamte Frontend neu schreiben zu müssen. Die Schritte umfassen die Installation des Adapters, die Konfiguration der astro.config.mjs mit entweder einer lokalen WordPress-Instanz oder einer Docker-Compose-Umgebung, das Erstellen eines theme-style.css und das Umbenennen von Seiten in .php.astro-Dateien, die zu echten WordPress-Template-Dateien kompilieren. Der Entwicklungs-Server leitet Anfragen live an WordPress weiter, sodass Änderungen sofort sichtbar sind, während `npm run build` ein aktivierbares Theme erstellt. Die Dokumentation behandelt häufige Fallstricke wie das Setzen von `partial = true` für PHP-Dateien ohne HTML-Dokument, Docker-spezifische Pfade und Fehlerbehebung bei 502-Fehlern. Für erweiterte Anpassungen wie ACF-Felder oder Menüs wird auf separate Skills verwiesen.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/sijad/astro-wordpress/tree/HEAD/skills/astro-wordpress

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Verwandelt eine statische Astro-Vorlage mit dem astro-wordpress-Adapter in ein WordPress-Theme: Seiten unter src/pages/*.php.astro werden zu echten WordPress-Template-Dateien kompiliert (index.php, page-template-*.php, …), während npm run dev an eine echte lokale WordPress-Instanz weiterleitet, sodass das Theme jederzeit live in der Vorschau angezeigt wird.

Dies ist das verifizierte Rezept, keine Paraphrase der README des Adapters: Die folgenden Schritte wurden auf eine echte statische Astro-Vorlage angewendet und Ende-zu-Ende bestätigt – der Dev-Server leitet live durch WordPress weiter, npm run build erzeugt ein aktivierbares Theme, wp theme activate funktioniert.

Voraussetzungen

  • Eine lokale WordPress-Installation, die über HTTP erreichbar ist. Zwei verifizierte Optionen:
    • Docker Compose (empfohlen – kein lokales PHP/MySQL/wp-cli erforderlich, und wp-cli ist auf dem Host möglicherweise nicht installiert). Siehe Schritt 0.
    • Eine bereits laufende lokale WP-Installation (beliebiger PHP-Server + MySQL/MariaDB, auf den devProxyTarget zeigt). Diese Fähigkeit konvertiert in beiden Fällen nur die Astro-Seite.
  • Node/npm für das Astro-Projekt.
  • wp-cli ist während dieser gesamten Fähigkeit optional – jeder wp-cli-Befehl unten hat einen Fallback ohne wp-cli (Browser/curl-Formularübermittlung oder einen dockerisierten wp-cli-Beitrag). Fügen Sie es nicht als harte Anforderung hinzu.

0. (Docker-Option) Starten Sie WordPress mit Docker Compose

Diese exakte compose.yaml (aus dem astro-wordpress-Starter) funktioniert unverändert – verifiziert durch tatsächliches Ausführen:

services:
  wordpress:
    image: wordpress
    restart: always
    ports:
      - 8088:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - ./wp:/var/www/html
      - ./public/:/var/www/html/public

  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: "1"
    volumes:
      - db:/var/lib/mysql

volumes:
  db:
docker compose up -d

Kein wp-cli im wordpress-Image standardmäßig – schließen Sie die Installation und alles andere entweder über den Browser (http://localhost:8088) oder mit einem einmaligen dockerisierten wp-cli-Container ab, der dasselbe Netzwerk + dieselben Volumes teilt (siehe Überprüfen/Häufige Fallstricke – dies ist das Muster, das Sie verwenden sollten, wenn ein Schritt unten wp ... sagt und kein lokales wp-cli installiert ist):

docker run --rm --network container:<wordpress-container-name> \
  --volumes-from <wordpress-container-name> -w /var/www/html \
  -e WORDPRESS_DB_HOST=db -e WORDPRESS_DB_USER=exampleuser \
  -e WORDPRESS_DB_PASSWORD=examplepass -e WORDPRESS_DB_NAME=exampledb \
  wordpress:cli <wp-cli-command>

(Die -e-Variablen müssen mit der Umgebung des wordpress-Dienstes übereinstimmen – der CLI-Container liest dieselbe wp-config.php, die sie über getenv() auflöst, erbt aber nicht die Umgebung des anderen Containers.)

Schritte

1. Installieren Sie den Adapter

npm install astro-wordpress

(passthroughImageService wird unten mit dem Astro-Kern ausgeliefert – kein zusätzliches Paket.)

2. Konfigurieren Sie astro.config.mjs

Bare-Metal-WP (Astro und WP auf demselben Host, keine Container-Grenze):

// @ts-check
import { defineConfig, fontProviders, passthroughImageService } from "astro/config";
import wordpress from "astro-wordpress";

export default defineConfig({
  server: {
    host: "127.0.0.1",
  },
  adapter: wordpress({
    devProxyTarget: "http://localhost:7001", // Ihre lokale WP-URL
    outDir: "./wp/wp-content/themes/<theme-name>", // Das erstellte Theme wird hier abgelegt
  }),
  image: {
    service: passthroughImageService(), // erforderlich – WP serviert/optimiert Bilder selbst
  },
});

Docker Compose WP (mit der obigen compose.yaml) benötigt drei weitere Optionen – jede wurde als notwendig verifiziert, indem sie tatsächlich ohne sie ausgeführt wurde (siehe Häufige Fallstricke):

export default defineConfig({
  server: {
    host: "0.0.0.0", // an allen Schnittstellen binden, damit der Container darauf zugreifen kann
    allowedHosts: ["host.docker.internal"],
  },
  adapter: wordpress({
    devProxyTarget: "http://localhost:8088",
    outDir: "./wp/wp-content/themes/<theme-name>",
    // Die eigene Sicht des WP-Containers auf das eingebundene public/-Verzeichnis –
    // NICHT der Host-Pfad (siehe Häufige Fallstricke)
    publicDirPath: "/var/www/html/public",
    // Ermöglicht dem PHP-Entwicklungs-Template-Stub, der *innerhalb* des Containers läuft,
    // eine Verbindung zum Astro-Entwicklungsserver auf dem Host herzustellen
    devServerTarget: "http://host.docker.internal:4321",
  }),
  image: { service: passthroughImageService() },
});

devProxyTarget muss mit der Adresse übereinstimmen, auf der WordPress tatsächlich lauscht. outDir ist das Verzeichnis, in das npm run build das fertige Theme schreibt; es muss nicht innerhalb des Astro-Projekts liegen. Wenn es das tut (ein vollständiger lokaler WP-Checkout, der z. B. unter ./wp/ verschachtelt ist), fügen Sie dieses Verzeichnis zu .gitignore hinzu – der WordPress-Kern und seine Uploads gehören nicht in das Repository des Astro-Projekts.

3. Fügen Sie das Theme-Stylesheet hinzu

WordPress erkennt ein Theme-Verzeichnis nur, wenn es eine style.css mit diesem Header hat – erstellen Sie public/style.css (es wird vom Adapter automatisch in outDir symlinkiert/kopiert):

/*!
Theme Name: <Theme Name>
Version: 0.0.1
*/

4. Konvertieren Sie Seiten zu .php.astro

Benennen Sie jede src/pages/*.astro-Route, die Sie von WordPress bedienen lassen möchten, in src/pages/*.php.astro um – der Standard-Export der Datei rendert weiterhin durch Astro/Ihre vorhandenen Layouts und Komponenten unverändert; nur die Erweiterung und das endgültige Ausgabeformat ändern sich (index.astro → index.php). Für eine korrekte Erstellung und Bereitstellung einer Seite sind keine weiteren Codeänderungen erforderlich.

Nicht-Index-WP-Template-Dateien folgen demselben Muster: Das Präfix page-template- wird automatisch erkannt und in einen /* Template Name: ... */-Kommentar umgewandelt, den WordPress für benutzerdefinierte Seitenvorlagen erkennt, z. B. src/pages/page-template-landing.php.astro → eine auswählbare „Landing“-Vorlage. (In der README des Adapters dokumentiert; von diesem Rezept nicht getestet.)

Für Dateien, die rohes PHP ohne umgebendes HTML-Dokument ausgeben müssen (z. B. eine functions.php.astro, die zum Registrieren von Hooks/Fields verwendet wird – siehe die Fähigkeit astro-wordpress-acf), fügen Sie export const partial = true; im Frontmatter hinzu. Ohne dies stellt Astro automatisch <!DOCTYPE html> vor die Ausgabe und beschädigt die PHP-Datei.

5. Aktivieren Sie das Theme

Allgemein: WP-Admin → Design → Themes → Aktivieren. Mit wp-cli (lokal oder dockerisiert, siehe Schritt 0):

npm run build
wp theme activate <theme-name> --path=<wp-dir>

Überprüfen

# 1. Dev-Server und WP laufen beide? Jede Anfrage wird über devProxyTarget weitergeleitet,
#    sodass selbst statische Assets 502 erhalten, wenn WP nicht erreichbar ist
npm run dev &
curl -o /dev/null -s -w "%{http_code}\n" http://127.0.0.1:4321/

# 2. Umgehen Sie den WP-Proxy, um die rohe Astro-gerenderte PHP-artige Ausgabe direkt
#    vom Dev-Server zu sehen – nützlich, um zu isolieren: "Ist das ein Astro-Problem
#    oder ein WordPress-Problem"
curl -s -H "by-pass-proxy: 1" http://127.0.0.1:4321/index.php | head -c 300

# 3. Produktions-Build legt echte, reines PHP in outDir ab
npm run build
grep -c '<?php' wp/wp-content/themes/<theme-name>/index.php

# 4. Theme ist aktiv – über wp-cli, oder laden Sie einfach die Startseite und prüfen Sie
#    auf themenspezifisches Markup, falls wp-cli nicht verfügbar ist
wp theme list --path=<wp-dir> | grep <theme-name>

Keine lokale WP-Installation zum Testen und möchten bestätigen, dass die WP-Installation selbst headless funktioniert (kein wp-cli, kein Browser)? Der Installationsassistent ist ein einfaches Formular-POST – genau so wurde eine frische WP-Installation für diese Fähigkeit verifiziert:

curl "http://localhost:8088/wp-admin/install.php?step=2" \
  --data-urlencode "weblog_title=My Site" \
  --data-urlencode "user_name=admin" \
  --data-urlencode "admin_password=<password>" \
  --data-urlencode "admin_password2=<password>" \
  --data-urlencode "pw_weak=1" \
  --data-urlencode "[email protected]" \
  --data-urlencode "Submit=Install WordPress"
# Dann auf die gleiche Weise anmelden (Cookie-Jar) für spätere Admin-Bildschirmprüfungen:
curl -c cookies.txt \
  --data-urlencode "log=admin" --data-urlencode "pwd=<password>" \
  --data-urlencode "wp-submit=Log In" \
  --data-urlencode "redirect_to=http://localhost:8088/wp-admin/" \
  --data-urlencode "testcookie=1" \
  "http://localhost:8088/wp-login.php"
curl -b cookies.txt "http://localhost:8088/wp-admin/" | grep -o "<title>[^<]*</title>"

Häufige Fallstricke

  • Jede Dev-Modus-Anfrage wird an devProxyTarget weitergeleitet, nicht nur .php-Seiten – /src, /@, /node_modules und alles mit einem by-pass-proxy-Header sind die einzigen Ausnahmen. Wenn WordPress nicht läuft, erhält die gesamte Site 502, einschließlich Bilder/Schriftarten unter public/. Überprüfen Sie, ob WP tatsächlich läuft, bevor Sie die Astro-Seite debuggen.
  • Astro 7s Dev-Server ist ein persistenter Hintergrund-Daemon. Ein zweites npm run dev bindet nicht neu oder verursacht keinen Fehler – es meldet nur die bereits laufende Instanz (npx astro dev status / stop / logs zur direkten Verwaltung).
  • export const partial = true; – siehe Schritt 4. Dies ist die mit Abstand am wenigsten offensichtliche Anforderung im gesamten Adapter; die Fehlerart (störendes <!DOCTYPE html> am Anfang einer PHP-Datei) scheint überhaupt nichts mit Astro zu tun zu haben.
  • publicDirPath muss der Pfad sein, wie der WP-Container ihn sieht, nicht der Host-Pfad. Der Adapter verlinkt jede public/-Datei mit dem von Ihnen angegebenen publicDirPath in das Theme-Verzeichnis. Mit Docker geben Sie den Container-Pfad an (/var/www/html/public) – bestätigt durch Überprüfen des resultierenden Symlinks in beide Richtungen: readlink wp-content/themes/<theme>/style.css → /var/www/html/public/style.css, was über docker exec <container> cat wp-content/themes/<theme>/style.css einwandfrei aufgelöst wird, aber vom Host-Shell aus „No such file or directory" ist. Wenn Sie publicDirPath weglassen, fällt der Adapter auf den Host-Pfad zurück, der innerhalb des Containers ungültig ist.
  • Die Daemon-Sperre von astro dev gilt pro Projektverzeichnis, nicht pro Konfiguration/Port. Das Ausführen von astro dev --config other.config.mjs --port 4325, während im selben Verzeichnis bereits ein einfaches astro dev läuft, meldet nur „Dev server already running" auf dem ursprünglichen Port – es startet keine zweite Instanz. Verwenden Sie zuerst astro dev stop, um die vorhandene Instanz zu beenden, wenn Sie die Konfiguration (z. B. Bare-Metal vs. Docker) im selben Projekt wechseln müssen.
  • Diese Konvertierung allein bindet wp_head()/wp_footer() nicht in das Layout ein, daher werden plugin-injizierte <script>/<style>-Tags, SEO-Plugin-Meta-Tags usw. nicht angezeigt. Die astro-wordpress-README zeigt das Hinzufügen von <Fragment set:html={} /> / <?php wp_footer(); ?> zum Layout dafür. Wenn das Layout sein eigenes <head> unabhängig aufbaut (häufig beim Portieren einer vorhandenen statischen Vorlage), behandeln Sie das Einbinden dieser als bewusste Folgemaßnahme, nicht als etwas, das die Schritte dieser Fähigkeit bereits bieten.
  • astro check (Teil von npm run build) kann abstürzen (OOM), wenn versucht wird, die WordPress-Kerndateien zu typüberprüfen, die in ./wp landen, sobald der Container startet (Tausende von .js/.php-Dateien unter wp-includes/js/dist/ usw.). Fügen Sie "exclude": ["dist", "wp"] zu tsconfig.json hinzu, bevor Sie einen Build mit bereits laufendem Docker-WP ausführen – sonst sieht der Fehler wie ein nicht zusammenhängender Node-Heap-Absturz ohne offensichtliche Verbindung zum WordPress-Adapter aus.
  • Biome (oder jeder Linter/Formatter, der über das gesamte Repository läuft) wird auch versuchen, ./wp zu verarbeiten, sobald es existiert, aus demselben Grund – fügen Sie einen Ignore-Eintrag hinzu (z. B. "files": { "ignore": ["wp/**"] } in biome.json), bevor Sie den Lint/Format-Befehl des Projekts ausführen.
  • Dynamische Rest-Param-Routen werden nicht konvertiert. src/pages/blog/[...slug].astro (oder jedes [...x].astro) kann nicht zu [...x].php.astro werden – Astros Router lehnt es rundweg ab („rest parameter must be a standalone segment"), weil das .php-Suffix die Segmentgrenze durchbricht. Lassen Sie diese Routen als einfaches .astro und außerhalb des WP-Themes, es sei denn, der Inhalt selbst wird in WP migriert.

Nächster Schritt

Sobald der Adapter eingerichtet ist:

  • astro-wordpress-acf – machen Sie bestimmte Abschnitte einer Seite über ACF im WP-Backend bearbeitbar.
  • astro-wordpress-menus – verbinden Sie eine Kopf-/Fußzeilen-/Navigationskomponente mit einem von WordPress verwalteten Menü (Design → Menüs) anstelle von fest codierten Links.
  • astro-wordpress-global-settings – fügen Sie eine siteweite „Theme Options"-Seite für Werte hinzu, die nicht an eine einzelne Seite gebunden sind (erfordert ACF Pro oder Secure Custom Fields).

Verwandte Skills