diff --git a/README.md b/README.md
index 76f3035..bef157b 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,267 @@
-# bavarianrankengine
+# Bavarian Rank Engine
-All-in-One-Plugin für SEO und GEO
\ No newline at end of file
+
+
+
+
+
+Ein WordPress-Plugin für AI-gestützte Meta-Beschreibungen, GEO-optimierte Strukturdaten, llms.txt und KI-Crawler-Management — entwickelt von [Donau2Space](https://donau2space.de).
+
+---
+
+## Was ist das Plugin?
+
+**Bavarian Rank Engine (BRE)** ist ein All-in-One-Plugin für SEO und GEO (Generative Engine Optimization). Es verbindet WordPress mit führenden KI-Anbietern, um Meta-Beschreibungen vollautomatisch beim Veröffentlichen eines Beitrags zu generieren, reichert Seiten mit schema.org-Strukturdaten an, stellt einen maschinenlesbaren Inhaltsindex unter `/llms.txt` bereit und ermöglicht die gezielte Steuerung von KI-Crawlern über `robots.txt` — alles aus einer einheitlichen Admin-Oberfläche heraus.
+
+Das Plugin ist so konzipiert, dass es ohne Reibung neben Rank Math, Yoast SEO, AIOSEO und SEOPress arbeitet, deren native Meta-Felder beschreibt und bestehende Beschreibungen niemals überschreibt.
+
+---
+
+## Features
+
+### AI Meta Generator
+
+Generiert beim Veröffentlichen automatisch eine SEO-optimierte Meta-Beschreibung (150–160 Zeichen). Der Prompt ist vollständig anpassbar und unterstützt die Platzhalter `{title}`, `{content}`, `{excerpt}` und `{language}`. Die Sprache wird automatisch aus Polylang, WPML oder dem WordPress-Locale ermittelt und an die KI weitergegeben.
+
+Generierte Beschreibungen werden sowohl in BREs eigenem Post-Meta-Feld `_bre_meta_description` als auch direkt im nativen Feld des aktiven SEO-Plugins gespeichert (Rank Math: `rank_math_description`, Yoast: `_yoast_wpseo_metadesc`, AIOSEO: `_aioseo_description`, SEOPress: `_seopress_titles_desc`).
+
+Zwei Hooks stehen für Entwickler bereit:
+- **`bre_prompt`** (Filter): Erlaubt es, den fertigen Prompt vor dem API-Aufruf zu modifizieren — z. B. um ein Focus-Keyword anzuhängen.
+- **`bre_meta_saved`** (Action): Wird nach dem Speichern einer Beschreibung gefeuert — z. B. für Synchronisation mit externen Systemen.
+
+### Fallback-Meta (FallbackMeta)
+
+Wenn kein API-Key hinterlegt ist oder ein KI-Aufruf fehlschlägt, extrahiert `FallbackMeta::extract()` automatisch eine saubere 150–160-Zeichen-Beschreibung aus dem Post-Content. Der Extraktor schneidet bevorzugt an Satzgrenzen (`.`, `!`, `?`) ab und fällt erst dann auf Wortgrenzen und schließlich auf einen harten Schnitt mit Ellipse zurück. Kein HTML im Ergebnis.
+
+### Bulk Generator
+
+Batch-Verarbeitung aller veröffentlichten Beiträge ohne Meta-Beschreibung. Der Bulk-Prozess läuft per wiederholtem AJAX-Request im Browser, verarbeitet 1–20 Beiträge pro Batch mit einem fest eingebautem 6-Sekunden-Delay zwischen Batches (Rate-Limiting). Jeder Beitrag wird bis zu dreimal versucht. Ein Live-Progress-Log und eine laufende Kostenabschätzung werden direkt in der Admin-UI angezeigt.
+
+**BulkQueue-Lock:** Ein Transient-basierter Mutex (`bre_bulk_running`, TTL 15 Minuten) verhindert gleichzeitige Bulk-Runs — auch über mehrere Browser-Tabs oder Admin-Nutzer hinweg. Das Lock wird beim Start des ersten Batches gesetzt und beim letzten Batch oder manuell über einen Button freigegeben.
+
+### Schema.org Enhancer (GEO)
+
+Gibt JSON-LD-Strukturdaten und Meta-Tags in `wp_head` aus. Jeder Typ ist individuell aktivierbar:
+
+| Typ | Schema.org-Type | Besonderheit |
+|---|---|---|
+| `organization` | `Organization` | Name, URL, Logo, `sameAs`-Links (Social) |
+| `article_about` | `Article` | Headline, Publish/Modified, Description, Publisher |
+| `author` | `Person` | Name, Autor-URL, optionaler Twitter-`sameAs` |
+| `speakable` | `WebPage` + `SpeakableSpecification` | CSS-Selektoren auf H1 und ersten Absatz |
+| `breadcrumb` | `BreadcrumbList` | Übersprungen wenn Rank Math oder Yoast aktiv |
+| `ai_meta_tags` | — | `` und `` mit `max-snippet:-1` |
+
+Die eigenständige ``-Ausgabe wird unterdrückt, wenn Rank Math, Yoast oder AIOSEO aktiv sind, um Doppelausgaben zu vermeiden.
+
+### llms.txt (mit ETag/Cache)
+
+Bedient `/llms.txt` (und paginierte Folgedateien `/llms-2.txt`, `/llms-3.txt` ...) über einen `parse_request`-Hook mit Priorität 1. Der Inhalt wird via WordPress-Transients gecacht und beim Speichern der Einstellungen automatisch invalidiert. HTTP-Caching-Header werden korrekt gesetzt:
+
+- `ETag: "md5(content)"` — HTTP 304 bei übereinstimmendem If-None-Match
+- `Last-Modified:` basierend auf dem neuesten `post_modified_gmt` in der Datenbank
+- `Cache-Control: public, max-age=3600`
+
+Die llms.txt enthält: Titel, Beschreibungs-Block vor dem Inhaltsverzeichnis, Featured-Links-Sektion, Content-Liste mit Datum, More-Sektion für Folgeseiten und optional einen Footer-Block.
+
+Wenn Rank Math ebenfalls eine llms.txt ausliefern will, zeigt BRE einen Admin-Hinweis an, dass BRE Priorität hat.
+
+### robots.txt Manager
+
+Hängt `User-agent: \nDisallow: /\n`-Blöcke über den WordPress-Filter `robots_txt` an. Unterstützte Bots:
+
+GPTBot, ClaudeBot, Google-Extended, PerplexityBot, CCBot, Applebot-Extended, Bytespider, DataForSeoBot, ImagesiftBot, omgili, Diffbot, FacebookBot, Amazonbot.
+
+Jeder Bot kann einzeln über Checkboxen im Admin aktiviert oder deaktiviert werden.
+
+### CrawlerLog (Privacy-konform)
+
+Loggt Besuche bekannter KI-Bots in eine eigene Datenbanktabelle (`{prefix}bre_crawler_log`):
+
+| Spalte | Inhalt |
+|---|---|
+| `bot_name` | Name des Bots (z. B. `GPTBot`) |
+| `ip_hash` | SHA-256-Hash der Besucher-IP — keine Original-IP wird gespeichert |
+| `url` | Aufgerufene URL (max. 512 Zeichen) |
+| `visited_at` | Zeitstempel des Besuchs |
+
+Einträge älter als 90 Tage werden automatisch per Weekly-Cron bereinigt. Das Dashboard zeigt eine 30-Tage-Zusammenfassung pro Bot.
+
+### Meta Editor Box
+
+Fügt einen Meta-Box-Block "Meta Description (BRE)" in den Post-Editor ein. Zeigt:
+- Eine Quellen-Badge (KI generiert / Fallback / Manuell / Noch nicht generiert)
+- Ein Textfeld mit `maxlength="160"` und Live-Zeichenzähler
+- Einen "Mit KI neu generieren"-Button (nur sichtbar wenn ein API-Key hinterlegt ist), der inline eine neue Beschreibung abruft
+
+### SEO Analyse Widget
+
+Eine Sidebar-Meta-Box im Post-Editor mit Live-Statistiken:
+- Titel-Länge (Ziel: 60 Zeichen)
+- Wortanzahl und geschätzte Lesezeit
+- Überschriften-Hierarchie (H1–H6)
+- Intern- und Externlinks-Zähler
+- Inline-Warnungen (z. B. kein H2, keine internen Links)
+
+Stats werden per JavaScript live aktualisiert, während der Redakteur schreibt.
+
+### Link-Analyse (Dashboard)
+
+Ein AJAX-Bereich auf dem Dashboard, der identifiziert:
+- Beiträge ohne einen einzigen internen Link
+- Beiträge mit überdurchschnittlich vielen externen Links (konfigurierbarer Schwellenwert)
+- Die Top-5-Pillar-Pages nach Anzahl eingehender interner Links
+
+Ergebnisse werden 1 Stunde im Transient-Cache gehalten.
+
+---
+
+## API-Key-Sicherheit (KeyVault)
+
+```
+Klartextkey → XOR(key, sha256(AUTH_KEY . SECURE_AUTH_KEY)) → base64 → "bre1:"
+```
+
+Die Klasse `BavarianRankEngine\Helpers\KeyVault` verschleiert API-Keys vor dem Schreiben in die WordPress-Optionstabelle:
+
+1. Ein 64-Zeichen-Hex-Salt wird aus den WordPress-Konstanten `AUTH_KEY` und `SECURE_AUTH_KEY` via `hash('sha256', AUTH_KEY . SECURE_AUTH_KEY)` abgeleitet.
+2. Der Klartext-Key wird byte-für-byte XOR-verknüpft (Salt wird bei Bedarf wiederholt).
+3. Das Ergebnis wird base64-kodiert und mit dem Präfix `bre1:` gespeichert.
+
+**Kein OpenSSL, keine PHP-Extension** außer der PHP-Standardbibliothek erforderlich.
+
+**Wichtiger Hinweis:** XOR mit einem statischen, abgeleiteten Salt ist Verschleierung, keine kryptografische Verschlüsselung. Ein Angreifer mit Zugriff auf sowohl die Datenbank als auch `wp-config.php` kann den Key rekonstruieren. Für maximale Sicherheit können Keys als Konstanten in `wp-config.php` definiert werden:
+
+```php
+define( 'BRE_OPENAI_KEY', 'sk-...' );
+define( 'BRE_ANTHROPIC_KEY', 'sk-ant-...' );
+define( 'BRE_GEMINI_KEY', 'AI...' );
+define( 'BRE_GROK_KEY', 'xai-...' );
+```
+
+In der Admin-UI werden Keys stets maskiert angezeigt: `••••••Ab3c9` (letzte 5 Zeichen sichtbar).
+
+---
+
+## Technischer Stack
+
+| Komponente | Technologie |
+|---|---|
+| Backend | PHP 8.0+, WordPress Plugin API |
+| Namespace | `BavarianRankEngine\` |
+| Architektur | Singleton-Core, Registry-Pattern für Provider, Feature-Klassen mit `register()` |
+| Datenbank | WordPress Options API, wpdb (eigene Tabelle für CrawlerLog) |
+| Caching | WordPress Transients (llms.txt, Link-Analyse, Bulk-Lock) |
+| Frontend | Vanilla JS + jQuery (WordPress-integriert), kein Build-Step |
+| I18n | `.pot`-File, Text-Domain `bavarian-rank-engine` |
+| Tests | PHPUnit via Composer |
+| Lizenz | GPL-2.0-or-later |
+
+---
+
+## Besonderheiten
+
+**llms.txt mit ETag/Cache-Kontrolle**
+Vollständige HTTP-Caching-Semantik inklusive 304-Not-Modified-Unterstützung. Der Content-Hash wird per `md5()` als ETag generiert. `Last-Modified` basiert auf dem neuesten `post_modified_gmt`-Timestamp in der Datenbank. Der Transient-Cache wird bei jeder Einstellungsänderung automatisch invalidiert.
+
+**Bulk mit Rate-Limiting und Mutex-Lock**
+Der 6-Sekunden-Inter-Batch-Delay und der 15-Minuten-Transient-Lock sind gezielt so implementiert, dass kein Produkt-API-Ratelimit ausgelöst wird und keine Race Conditions zwischen parallelen Admin-Sessions entstehen können.
+
+**Fallback-Meta mit Satzgrenzerkennung**
+`FallbackMeta::extract()` versucht aktiv, am Ende eines vollständigen Satzes (`. `, `! `, `? `) zu schneiden, bevor es auf Wortgrenzen und schließlich auf einen harten Schnitt zurückfällt. Multibyte-safe via `mb_substr` / `mb_strrpos`.
+
+**CrawlerLog ohne Personenbezug**
+IP-Adressen werden vor dem Speichern mit SHA-256 gehasht. Die Originale werden nie persistiert, was die Anforderungen der DSGVO an Datenminimierung erfüllt.
+
+**Keine Doppel-Ausgaben bei SEO-Plugin-Koexistenz**
+`hasExistingMeta()` prüft alle bekannten Meta-Felder (BRE, Rank Math, Yoast, AIOSEO, SEOPress) und überspringt Posts, die in einem davon bereits eine Beschreibung haben. `outputMetaDescription()` unterdrückt die eigene ``-Ausgabe wenn ein kompatibles SEO-Plugin erkannt wird.
+
+---
+
+## Installation für Entwickler
+
+```bash
+# Repository klonen
+git clone https://git.donau2space.de/Michael/bavarianrankengine.git
+cd bavarianrankengine
+
+# Dev-Abhängigkeiten installieren (PHPUnit)
+composer install
+
+# Testsuite ausführen
+php vendor/bin/phpunit --testdox
+```
+
+Für eine lokale WordPress-Instanz (z. B. mit wp-env oder Local by Flywheel):
+
+```bash
+# Plugin-Verzeichnis verlinken oder kopieren
+ln -s $(pwd) /path/to/wordpress/wp-content/plugins/bavarian-rank-engine
+
+# Plugin in WordPress aktivieren
+wp plugin activate bavarian-rank-engine
+```
+
+Das Plugin hat keinen JavaScript-Build-Step. Alle Assets unter `assets/` sind direkte JS/CSS-Dateien.
+
+---
+
+## Contributing / Extending
+
+### Neuen KI-Provider hinzufügen
+
+1. Datei `includes/Providers/YourProvider.php` erstellen und `ProviderInterface` implementieren:
+
+```php
+namespace BavarianRankEngine\Providers;
+
+class YourProvider implements ProviderInterface {
+ public function getId(): string { return 'yourprovider'; }
+ public function getName(): string { return 'Your Provider'; }
+ public function getModels(): array { return [ 'model-id' => 'Model Name' ]; }
+
+ public function testConnection( string $api_key ): array {
+ // Minimaler API-Call, gibt ['success' => bool, 'message' => string] zurück
+ }
+
+ public function generateText( string $prompt, string $api_key, string $model, int $max_tokens = 300 ): string {
+ // API aufrufen, Text zurückgeben, \RuntimeException bei Fehler werfen
+ }
+}
+```
+
+2. In `includes/Core.php` in `register_hooks()` registrieren:
+
+```php
+$registry->register( new Providers\YourProvider() );
+```
+
+Der Provider erscheint automatisch in allen Admin-Dropdowns.
+
+### Neues Feature hinzufügen
+
+1. `includes/Features/YourFeature.php` mit einer `register()`-Methode erstellen, die WordPress-Hooks anhängt.
+2. `require_once BRE_DIR . 'includes/Features/YourFeature.php';` in `Core::load_dependencies()` ergänzen.
+3. `( new Features\YourFeature() )->register();` in `Core::register_hooks()` ergänzen.
+
+### Hooks für externe Nutzung
+
+```php
+// Prompt vor dem API-Aufruf anpassen
+add_filter( 'bre_prompt', function( string $prompt, \WP_Post $post ): string {
+ return $prompt . "\nFokus-Keyword: " . get_post_meta( $post->ID, 'focus_keyword', true );
+}, 10, 2 );
+
+// Nach dem Speichern einer Meta-Beschreibung reagieren
+add_action( 'bre_meta_saved', function( int $post_id, string $description ): void {
+ my_external_sync( $post_id, $description );
+}, 10, 2 );
+```
+
+---
+
+## Lizenz
+
+GPL-2.0-or-later — siehe [https://www.gnu.org/licenses/gpl-2.0.html](https://www.gnu.org/licenses/gpl-2.0.html)
+
+Copyright (c) 2025 [Donau2Space](https://donau2space.de)