diff --git a/Communities/openreli/matrix-wordpress.md b/Communities/openreli/matrix-wordpress.md
new file mode 100644
index 0000000..75ed310
--- /dev/null
+++ b/Communities/openreli/matrix-wordpress.md
@@ -0,0 +1,705 @@
+# Matrix Chat Widget – Dokumentation
+
+**Projekt:** Öffentliche Leseanzeige eines Matrix-Raums auf einer WordPress-Seite
+**Homeserver:** `matrix.rpi-virtuell.de`
+**Element-Client:** `element.rpi-virtuell.de`
+**Raum-ID:** `!NQPmoqtLSjGzdtLaXO:rpi-virtuell.de`
+**Stand:** März 2026
+
+---
+
+## Kontext und Problemlage
+
+Ziel war es, einen öffentlichen Matrix-Raum als Leseanzeige (kein Login für Besucher:innen erforderlich) in eine WordPress-Seite einzubetten. Dabei wurden folgende Wege geprüft und verworfen:
+
+**Matrix Public Archive / Matrix Viewer** – wurde eingestellt.
+
+**matrix-live (live.hello-matrix.net)** – funktioniert nur mit Homeservern, die Guest Access aktiviert haben.
+
+**Guest Access** – auf `matrix.rpi-virtuell.de` nicht aktiviert; auf `matrix.org` seit Januar 2025 abgeschaltet.
+
+**Element Web als iFrame** – `app.element.io` und die meisten selbst gehosteten Instanzen setzen `X-Frame-Options: DENY` und können nicht eingebettet werden.
+
+**Gewählte Lösung:** Ein eigenständiges HTML/JS-Widget, das direkt die Matrix Client-Server API abfragt. Voraussetzung ist ein dedizierter Bot-Account mit Lesezugriff, dessen Token fest im Widget hinterlegt ist. Das ist unkritisch, da der Token nur Lesezugriff auf einen öffentlichen Raum hat.
+
+---
+
+## Voraussetzungen
+
+### 1. Raum auf „world_readable" setzen
+
+In Element: **Raumeinstellungen → Sicherheit & Datenschutz → „Wer kann den Verlauf lesen?" → „Jeder"**
+
+Ohne diese Einstellung antwortet die API mit HTTP 403.
+
+### 2. Bot-Account anlegen und Token holen
+
+Einen dedizierten Account (z. B. `@openrelibot:rpi-virtuell.de`) anlegen und einmalig per API einloggen:
+
+```bash
+curl -X POST https://matrix.rpi-virtuell.de/_matrix/client/v3/login \
+ -H "Content-Type: application/json" \
+ -d '{"type":"m.login.password","user":"openrelibot","password":"PASSWORT"}'
+```
+
+Die Antwort enthält `access_token` – dieser wird im Widget als `TOKEN` eingetragen.
+
+> **Hinweis:** Da der Token in einem Chatprotokoll sichtbar war, sollte er bei nächster Gelegenheit rotiert werden (siehe Abschnitt Token-Rotation).
+
+---
+
+## Einbindung in WordPress
+
+Gutenberg-Editor → Block **„Benutzerdefiniertes HTML"** → vollständigen Widget-Code einfügen → Speichern.
+
+Kein Plugin erforderlich. Der Code ist vollständig eigenständig (kein externes CDN, keine Abhängigkeiten).
+
+---
+
+## Vollständiger Code
+
+```html
+
+
+
+
+
+
+
+```
+
+---
+
+## Technische Dokumentation
+
+### Architektur
+
+Das Widget ist eine einzelne, vollständig eigenständige HTML-Datei ohne externe Abhängigkeiten. Es kommuniziert direkt mit der Matrix Client-Server API (v3) des Homeservers per `fetch()`.
+
+```
+Browser → fetch() → matrix.rpi-virtuell.de/_matrix/client/v3/...
+ → /_matrix/media/v3/download/... (Bilder)
+```
+
+### Verwendete API-Endpunkte
+
+| Endpunkt | Zweck |
+|---|---|
+| `GET /rooms/{roomId}/state/m.room.name/` | Raumname laden |
+| `GET /rooms/{roomId}/state/m.room.avatar/` | Raumlogo laden (mxc-URL) |
+| `GET /rooms/{roomId}/messages?dir=b&limit=N` | Letzte Nachrichten abrufen |
+| `GET /profile/{userId}/avatar_url` | Benutzer-Avatar laden (mxc-URL) |
+| `GET /_matrix/media/v3/download/{server}/{id}` | Mediendatei (Bild) abrufen |
+
+Alle Requests senden den `Authorization: Bearer {TOKEN}` Header, da der Homeserver auch für world-readable Räume Authentifizierung verlangt (HTTP 401 ohne Token).
+
+### Konfigurationsparameter
+
+```javascript
+const HOMESERVER = 'https://matrix.rpi-virtuell.de'; // Matrix-Homeserver
+const ROOM_ID = '!NQPmoqtLSjGzdtLaXO:rpi-virtuell.de'; // Raum-ID
+const LIMIT = 40; // Anzahl angezeigter Top-Level-Nachrichten
+const POLL_SEC = 30; // Polling-Intervall in Sekunden
+const TOKEN = '...'; // Access Token des Bot-Accounts
+```
+
+### Nachrichten-Typen und Darstellung
+
+Das Widget unterscheidet vier Typen von Events anhand des `m.relates_to`-Feldes:
+
+**Normale Nachricht** – kein `m.relates_to` → wird auf Top-Level gerendert.
+
+**Bearbeitete Nachricht** (`rel_type: "m.replace"`) → wird nicht als separate Nachricht angezeigt. Stattdessen überschreibt das neueste Replace-Event den Inhalt der Originalnachricht. In der Zeitzeile erscheint kursiv *(bearbeitet)*.
+
+**Klassische Reply** (`m.in_reply_to`, kein `rel_type: m.thread`) → wird um 46 px eingerückt dargestellt, mit grauer linker Borderlinie und einer grünen Zitiervorschau des Originaltexts. Element bettet den zitierten Text als `> Zitat\n\nAntwort` in den `body` ein – das Widget extrahiert dieses Muster per `split('\n\n')`.
+
+**Thread-Reply** (`rel_type: "m.thread"`, `event_id` = Root-Event-ID) → wird unter der Root-Nachricht gesammelt und erst nach Klick auf den Toggle-Button sichtbar. Der aufgeklappte Thread-Container hat eine grüne linke Borderlinie und kleinere Avatare (26 px statt 36 px).
+
+### Rendering-Pipeline
+
+```
+fetchMessages()
+ → API: /messages?dir=b&limit=120
+ → events.reverse() // chronologisch sortieren
+ → Edit-Deduplizierung:
+ latestEdit{} sammeln (m.replace)
+ Replace-Events herausfiltern
+ Originale mit m.new_content patchen + _edited:true
+ → patchedEvents.slice(-40) // letzte 40 behalten
+ → getUserAvatarUrl() parallel // Avatare vorladen
+ → Sortierung: byId{}, threads{}, topLevel[]
+ → topLevel.forEach → buildMsgEl()
+ → threads[e.event_id] → Toggle + threadEl
+ → Orphan-Thread-Kinder anhängen
+```
+
+Das Ladefenster (`limit = LIMIT * 3 = 120`) ist größer als die angezeigten 40 Nachrichten, um sicherzustellen, dass zu den angezeigten Top-Level-Nachrichten auch ihre zugehörigen Edit- und Thread-Events im selben API-Response enthalten sind.
+
+### mxc-URLs
+
+Matrix speichert Mediendateien intern als `mxc://server/id`. Die Funktion `mxcToHttp()` konvertiert diese in reguläre HTTPS-URLs:
+
+```
+mxc://rpi-virtuell.de/AbcXyz
+→ https://matrix.rpi-virtuell.de/_matrix/media/v3/download/rpi-virtuell.de/AbcXyz
+```
+
+### Avatar-Caching
+
+Um bei jedem Polling-Zyklus unnötige API-Aufrufe zu vermeiden, werden User-Avatare in einem In-Memory-Objekt `avatarCache` gespeichert (`mxid → URL | null`). Pro Rendering-Durchlauf werden alle einzigartigen Absender parallel vorgeladen (`Promise.all`), bevor die Nachrichten gerendert werden.
+
+### Fallback-Logik für Avatare
+
+Ist kein Profilbild hinterlegt oder schlägt das Laden fehl (`onerror`), zeigt das Widget einen farbigen Kreis mit den ersten zwei Buchstaben des Localparts. Die Farbe wird deterministisch per Hash-Funktion aus der vollständigen MXID berechnet – dieselbe Person hat immer dieselbe Farbe.
+
+### XSS-Schutz
+
+Alle aus der API stammenden Texte (Absendername, Nachrichtentext, Zitiervorschau) werden durch `escapeHtml()` bereinigt, bevor sie per `innerHTML` eingefügt werden. Bilder werden nur als `
` eingebettet, nie als HTML aus dem Event-Content übernommen.
+
+### Statusanzeige
+
+Der kleine Punkt oben rechts im Header zeigt den Verbindungsstatus:
+
+- 🟡 pulsierend – Ladevorgang
+- 🟢 grün – letzter API-Aufruf erfolgreich
+- 🔴 rot – Fehler (403 Forbidden oder Netzwerkfehler)
+
+### Polling statt WebSocket
+
+Das Widget verwendet Polling alle 30 Sekunden statt einer persistenten WebSocket-Verbindung (`/sync`). Begründung: WordPress-Seiten haben oft viele gleichzeitige Besucher:innen. Ein dauerhafter Sync-Kanal pro Seitenaufruf würde den Homeserver stark belasten. Polling ist hier ausreichend und deutlich ressourcenschonender.
+
+---
+
+## Anpassungsmöglichkeiten
+
+**Höhe des Chat-Bereichs** – CSS: `#matrix-messages { height: 420px; }`
+
+**Anzahl der Nachrichten** – `const LIMIT = 40;`
+
+**Polling-Frequenz** – `const POLL_SEC = 30;` (nicht unter 10 setzen)
+
+**Farbe des Headers** – `#matrix-chat-header { background: #0dbd8b; }` (Matrix-Grün)
+
+**„Mitschreiben"-Link** – URL im `` im HTML-Teil anpassen
+
+---
+
+## Token-Rotation
+
+Da der Token im Klartext im Code steht, sollte er bei Bedarf rotiert werden:
+
+```bash
+# Alten Token invalidieren
+curl -X POST https://matrix.rpi-virtuell.de/_matrix/client/v3/logout \
+ -H "Authorization: Bearer ALTERTOKEN"
+
+# Neuen Token holen
+curl -X POST https://matrix.rpi-virtuell.de/_matrix/client/v3/login \
+ -H "Content-Type: application/json" \
+ -d '{"type":"m.login.password","user":"openrelibot","password":"PASSWORT"}'
+```
+
+Neuen `access_token` im Code als `TOKEN` einsetzen und WordPress-Seite aktualisieren.