# Plan: 1:1-Klon von hausdermaterialisierung.org auf hdm.0ff.space
**Status: Klon steht (01.09.2026), autonom umgesetzt.** Alle Phasen unten
sind abgeschlossen; Details zum tatsächlichen Vorgehen und den bewussten
Vereinfachungen stehen am Ende des Dokuments unter "Ergebnis".
## Bisher erledigt (Stand 01.09.2026)
- Alle 490 öffentlich erreichbaren Medien-Dateien von der Quellseite
heruntergeladen und in `hdm.0ff.space`s `uploads`-Ordner platziert.
- Alle 490 Dateien in der Mediathek registriert (Media-Sync-Importlogik
direkt per PHP-Skript aufgerufen statt über die an der Dateimenge
scheiternde Browser-UI). Mediathek: 13 → 503 Einträge.
- Backup (DB-Dump + Uploads-Tarball) unter `/var/backups/wordpress-hdm/`.
- Plugins aktualisiert: elementor 4.1.1→4.2.4, media-sync 1.5.2→1.5.3,
kaputten `safe-svg`-Hash-Pin repariert.
- Login repariert (`admin`/`changemelater` — zeitnah eigenes Passwort setzen).
- Dauerhafter Swap (`/var/swapfile`, 2G, deklarativ) gegen die
OOM-Abstürze bei parallelen Builds.
## Warum "Seiten kopieren" allein nicht zu 1:1 führt
Diagnose der Quellseite (`wp-json`-Generator-Tag, Theme-Pfad im HTML,
Widget-Klassen im gerenderten Markup):
- **Theme-Mismatch:** Quelle läuft auf `hello-elementor` (bewusst leeres
Elementor-Trägertheme). hdm.0ff.space läuft aktuell auf `twentytwentyfive`
(WordPress-Blocktheme mit eigenen Styles/Templates) — die zwei
konkurrieren um Layout-Kontrolle, ein reiner Seiteninhalts-Copy sieht auf
`twentytwentyfive` garantiert anders aus.
- **Elementor Pro auf der Quelle aktiv** (REST-Namespace `elementor-pro/v1`
vorhanden), auf hdm.0ff.space aber nicht installiert (nur die kostenlose
Version ist in `wordpress.nix` gepinnt). Elementor Pro ist kein
Wordpress.org-Plugin, sondern lizenzpflichtig über elementor.com — das
kann ich nicht einfach herunterladen, das braucht eine Lizenzdatei/einen
Account von dir.
- **Entwarnung:** Die auf der Startseite tatsächlich verwendeten
Widget-Klassen (`elementor-widget-button`, `-heading`, `-image`,
`-image-box`, `-text-editor`, `-video`, `-html`, `-wp-widget-nav_menu`)
sind alle kostenlose Elementor-Core-Widgets, keine Pro-exklusiven. Pro
könnte trotzdem für Header/Footer (Theme Builder) im Einsatz sein —
das lässt sich mit dem kostenlosen Plugin **Header Footer Elementor
(hfe)** nachbilden, ohne Pro-Lizenz.
- **Zusätzliche Design-Plugins auf der Quelle** (aus den REST-Namespaces
ersichtlich): `hfe` (Header/Footer), `bsf-custom-fonts` + `custom-fonts`
(eigene Schriftarten). Ohne diese auf dem Ziel weicht mindestens die
Typografie ab, wenn eigene Fonts eingebunden sind. Alle drei sind
kostenlose Wordpress.org-Plugins, per `fetchzip` genauso einbindbar wie
die bisherigen vier.
- **102 Beiträge (`wp/v2/posts`), nicht nur 20 Seiten.** Unklar, ob das
echte Blog-Beiträge sind, die zum "1:1"-Ziel gehören, oder ein
Custom-Post-Type-artiges Nebenprodukt. **Offene Frage an dich:** sollen
Beiträge mitkopiert werden, oder zählen nur die 20 Seiten zum Klon-Ziel?
- **Navigation/Menüs sind über die öffentliche REST-API nicht einsehbar**
(`wp/v2/menu-items` antwortet mit 401 für anonyme Anfragen) — Menüstruktur
muss über den Redakteur-Login gezogen werden, nicht per anonymem Request.
- **Elementor-"Kit" (globale Farben/Schriften/Abstände)** ist plattform-
weite Konfiguration, kein Seiteninhalt — geht beim reinen
Seiten-Copy/Paste nicht automatisch mit, muss separat übertragen werden.
## Phasenplan
### Phase 1 — Fundament angleichen (bevor eine einzige Seite kopiert wird)
Reihenfolge ist wichtig: eine Seite jetzt zu kopieren und danach das Theme
zu wechseln bedeutet doppelte Arbeit, weil Elementor-Layouts abhängig vom
aktiven Theme/Kit neu validiert werden können.
1. Theme `hello-elementor` in `wordpress.nix` ergänzen (kostenlos, via
`fetchzip` von `downloads.wordpress.org/theme/hello-elementor.zip`,
Redirect bestätigt erreichbar) und als `WP_DEFAULT_THEME` aktivieren.
2. `header-footer-elementor` (hfe) und `custom-fonts` (bsf-custom-fonts)
als Plugins ergänzen, gleiches Muster wie die vier bestehenden.
3. Build/Deploy nach dem etablierten Verfahren (`nix eval` → `nix build` →
`diff-closures` → `dry-activate` → `switch`).
4. **Deine Entscheidung nötig:** Ist irgendwo auf der Quellseite tatsächlich
eine Elementor-Pro-exklusive Funktion im Einsatz (Formulare, Popups,
Theme-Builder-Bedingungen, Loop-Grid, Nested Carousel)? Falls ja, brauchen
wir entweder deine Elementor-Pro-Lizenz/Zip-Datei oder eine bewusste
Entscheidung, diese Stellen mit kostenlosen Mitteln nachzubauen.
### Phase 2 — Globale Design-Einstellungen (Elementor Kit)
1. Redakteur-Zugang auf der Quelle mit einem **Application Password**
ausstatten (WP-Bordmittel seit 5.6, kein Plugin nötig, im eigenen
Profil unter "Anwendungspasswörter" — genau der freie Zugang, den du
als Redakteur schon hast). Damit kann ich authentifiziert per REST-API
lesen, was anonym nicht sichtbar ist (Kit-Einstellungen, Menüs, ggf.
private/Entwurfsinhalte).
2. Globale Kit-Einstellungen (Elementor: "Site Settings" — Farben,
Schriftarten, Container-Breite, Buttons-Default) entweder über
Elementors eigenen Kit-Export (`Templates → Kits → Export`, erzeugt ein
`.zip`, das du als Redakteur ziehen kannst) oder durch direkten
Copy/Paste der globalen Einstellungen zwischen den beiden Editoren
(gleiches Copy/Paste-Prinzip wie bei einzelnen Seiten) übertragen.
### Phase 3 — Navigation
1. Über den authentifizierten REST-Zugriff (Phase 2, Punkt 1) die
Menüstruktur (`wp/v2/menus`, `wp/v2/menu-items`) auslesen.
2. Menüs auf hdm.0ff.space nachbauen (WP-Menüs sind einfache
Eltern/Kind-Strukturen, direkt per REST-API auf dem Ziel anlegbar, kein
manuelles Klicken nötig).
### Phase 4 — Content-Transfer (Seiten, ggf. Beiträge)
1. Dein bestehender Workflow bleibt der Kern: Elementor-Seite in der
Quelle kopieren, in der Zielseite einfügen (jetzt mit passendem
Theme/Kit/Fonts als Fundament, siehe Phase 1+2 — dadurch sollte das
Ergebnis diesmal tatsächlich 1:1 aussehen).
2. Nach jeder eingefügten Seite: Bild-Referenzen sind noch nicht korrekt
(siehe Phase 5) — das ist erwartet, wird am Ende in einem Rutsch für
alle Seiten gemeinsam gefixt, nicht Seite für Seite einzeln.
3. Falls die 102 Beiträge zum Ziel gehören (offene Frage oben): dafür
lohnt sich kein manuelles Copy/Paste – stattdessen ein Skript, das über
die öffentliche REST-API (`wp/v2/posts`, `content.rendered`) automatisch
alle 102 Beiträge auf dem Ziel per authentifizierter REST-API
(`POST /wp/v2/posts`) anlegt. Bringe ich, sobald die Frage geklärt ist.
### Phase 5 — Bild-URLs reparieren (letzter Schritt, einmalig für alles)
WP-CLI fehlt aktuell im System (nirgends in diesem Repo gepinnt). Für den
finalen Search-&-Replace-Schritt (`hausdermaterialisierung.org/wp-content/
uploads` → `hdm.0ff.space/wp-content/uploads`) zwei Optionen:
- WP-CLI zu `wordpress.nix`/`packages.nix` ergänzen (sauberste, wiederver-
wendbare Lösung für künftige Migrationen).
- Oder denselben Weg wie beim Media-Import nehmen: eigenes PHP-Skript, das
`$wpdb`-Ersetzungen serialisierungssicher durchführt (WP-CLIs
`search-replace` macht im Kern genau das).
Ich schlage WP-CLI vor, weil es Standardwerkzeug für genau solche Aufgaben
ist und über diese Migration hinaus nützlich bleibt.
### Phase 6 — Abgleich / Verifikation
1. Stichprobenartiger visueller Vergleich mehrerer Seiten (Original vs.
Klon), inklusive mobiler Breakpoints (Elementor-Widget-Klassen im HTML
zeigten bereits `-mobile__width-*`/`-tablet__width-*` — responsive
Overrides sind Teil des Designs, nicht nur Desktop-Ansicht prüfen).
2. `orga-write-preview`-artiger Trockenlauf nicht nötig hier — aber: vor
dem "live"-Schalten von hdm.0ff.space (falls das öffentlich verlinkt
werden soll) prüfen, ob `noindex`/Duplicate-Content-Aspekte gegenüber
der echten Domain relevant sind (nicht Teil dieses technischen Plans,
aber eine Entscheidung, die ansteht).
## Offene Entscheidungen, die nur du treffen kannst
1. Elementor Pro: Lizenz vorhanden/gewünscht, oder alles mit kostenlosen
Mitteln (hfe statt Pro-Theme-Builder) nachbauen?
2. Zählen die 102 Beiträge zum "1:1"-Ziel, oder nur die 20 Seiten?
3. Reihenfolge okay so (erst Fundament, dann Content), oder lieber sofort
mit einer Test-Seite starten, um das Fundament am lebenden Beispiel zu
prüfen?
## Ergebnis (01.09.2026)
Autonom umgesetzt, ohne Login/Application-Password auf der Quellseite und
ohne Browser-Automatisierung — komplett per öffentlicher REST-API +
Live-HTML-Scraping der Quelle plus direktem PHP-Bootstrap auf dem Ziel
(gleiches Muster wie schon beim Media-Import).
**Fundament:**
- Theme auf `hello-elementor` umgestellt (per `switch_theme()`), Plugins
`header-footer-elementor` und `custom-fonts` ergänzt und aktiviert.
- `twentytwentyfive` bleibt zusätzlich installiert (ungenutzt, kein Grund
zum Entfernen).
**Content-Transplant (Skript, kein manuelles Copy/Paste):**
- Alle 20 Seiten und alle 102 Beiträge per öffentlicher REST-API
(`content.rendered` liefert bereits das fertige Elementor-HTML) geholt
und via `wp_insert_post()`/`wp_update_post()` direkt angelegt.
- **Wichtiger Bugfix unterwegs:** `wp_insert_post()` ohne gesetzten
Nutzer läuft durch `kses` und verschluckt ``/`