{
"event": "PreToolUse",
"tool_name": "mcp__mcp-docs__docs_update",
"tool_input": {
"id": 145,
"content": "<nav class=\"breadcrumb\">\n <a href=\"\/docs\">Dokumentation<\/a> » <a href=\"\/docs\/frontend\">Frontend<\/a> » HTMX\n<\/nav>\n\n<h1>HTMX<\/h1>\n<p>HTMX ist die <strong>einzige erlaubte Methode<\/strong> für AJAX-Interaktionen im Campus-System.<\/p>\n\n<h2>Warum HTMX?<\/h2>\n<table>\n <tr><th>Aspekt<\/th><th>HTMX<\/th><th>fetch()\/XHR<\/th><\/tr>\n <tr><td>CSRF-Enforcement<\/td><td>Automatisch via Contract\/Hook<\/td><td>Manuell, fehleranfällig<\/td><\/tr>\n <tr><td>Konsistenz<\/td><td>Deklarativ im HTML<\/td><td>Imperativ in JS verstreut<\/td><\/tr>\n <tr><td>Server-Autorität<\/td><td>Ja<\/td><td>Client-State-Chaos möglich<\/td><\/tr>\n <tr><td>Progressive Enhancement<\/td><td>Ja<\/td><td>Nein<\/td><\/tr>\n <tr><td>Debugging<\/td><td>HTML-Attribute sichtbar<\/td><td>DevTools nötig<\/td><\/tr>\n<\/table>\n\n<h2>Contract #14: htmx-patterns<\/h2>\n<p>Alle HTMX-Regeln sind in Contract #14 definiert und werden durch Pre-Hooks enforced.<\/p>\n\n<h3>Kritische Regeln (BLOCK)<\/h3>\n<table>\n <tr><th>ID<\/th><th>Regel<\/th><th>Enforcement<\/th><\/tr>\n <tr><td>HTMX-C1<\/td><td><code>hx-post<\/code> MUSS <code>hx-headers<\/code> mit X-CSRF-TOKEN haben<\/td><td>Pre-Hook BLOCK<\/td><\/tr>\n <tr><td>HTMX-C2<\/td><td><code>hx-delete<\/code> MUSS <code>hx-headers<\/code> mit X-CSRF-TOKEN haben<\/td><td>Pre-Hook BLOCK<\/td><\/tr>\n <tr><td>HTMX-C3<\/td><td><code>hx-patch<\/code> MUSS <code>hx-headers<\/code> mit X-CSRF-TOKEN haben<\/td><td>Pre-Hook BLOCK<\/td><\/tr>\n <tr><td>HTMX-C4<\/td><td><code>hx-delete<\/code> MUSS <code>hx-confirm<\/code> Attribut haben<\/td><td>Pre-Hook BLOCK<\/td><\/tr>\n <tr><td>HTMX-C5<\/td><td><code>hx-put<\/code> MUSS <code>hx-headers<\/code> mit X-CSRF-TOKEN haben<\/td><td>Pre-Hook BLOCK<\/td><\/tr>\n<\/table>\n\n<h3>Empfohlene Regeln (WARN)<\/h3>\n<table>\n <tr><th>ID<\/th><th>Regel<\/th><th>Enforcement<\/th><\/tr>\n <tr><td>HTMX-R1<\/td><td>Kein fetch() in View-Dateien<\/td><td>Post-Hook WARN<\/td><\/tr>\n <tr><td>HTMX-R2<\/td><td><code>hx-indicator<\/code> für Loading-States<\/td><td>Dokumentation<\/td><\/tr>\n <tr><td>HTMX-R3<\/td><td><code>hx-swap<\/code> explizit angeben<\/td><td>Dokumentation<\/td><\/tr>\n <tr><td>HTMX-R4<\/td><td><code>hx-disabled-elt<\/code> für Button-States<\/td><td>Dokumentation<\/td><\/tr>\n<\/table>\n\n<h2>Standard-Patterns<\/h2>\n\n<h3>1. Button mit POST-Action<\/h3>\n<pre><code><button hx-post=\"\/api\/endpoint\"\n hx-headers='{\"X-CSRF-TOKEN\": \"<?= $csrfToken ?>\"}'\n hx-target=\"#result\"\n hx-swap=\"innerHTML\"\n hx-indicator=\"this\"\n hx-disabled-elt=\"this\">\n <span class=\"htmx-content\">Speichern<\/span>\n <span class=\"htmx-indicator\">Wird gespeichert...<\/span>\n<\/button><\/code><\/pre>\n\n<h3>2. Delete mit Confirmation<\/h3>\n<pre><code><button hx-delete=\"\/api\/items\/<?= $id ?>\"\n hx-headers='{\"X-CSRF-TOKEN\": \"<?= $csrfToken ?>\"}'\n hx-confirm=\"Wirklich löschen?\"\n hx-target=\"closest tr\"\n hx-swap=\"outerHTML swap:0.3s\">\n Löschen\n<\/button><\/code><\/pre>\n\n<h3>3. Form mit PUT<\/h3>\n<pre><code><form hx-put=\"\/api\/items\/<?= $id ?>\"\n hx-headers='{\"X-CSRF-TOKEN\": \"<?= $csrfToken ?>\"}'\n hx-target=\"#form-message\"\n hx-swap=\"innerHTML\"\n hx-indicator=\"#save-btn\"\n hx-disabled-elt=\"#save-btn\">\n <!-- Form fields -->\n <button type=\"submit\" id=\"save-btn\">Speichern<\/button>\n<\/form>\n<div id=\"form-message\"><\/div><\/code><\/pre>\n\n<h3>4. Inline-Edit<\/h3>\n<pre><code><input type=\"text\" \n name=\"value\"\n value=\"<?= htmlspecialchars($value) ?>\"\n hx-post=\"\/api\/items\/<?= $id ?>\/field\"\n hx-headers='{\"X-CSRF-TOKEN\": \"<?= $csrfToken ?>\"}'\n hx-trigger=\"blur, keyup[key=='Enter']\"\n hx-swap=\"none\"\n hx-disabled-elt=\"this\"\n hx-on::after-request=\"this.classList.toggle('is-saved', event.detail.successful)\"><\/code><\/pre>\n\n<h3>5. Select mit Auto-Save<\/h3>\n<pre><code><select name=\"status\"\n hx-post=\"\/api\/items\/<?= $id ?>\/status\"\n hx-headers='{\"X-CSRF-TOKEN\": \"<?= $csrfToken ?>\"}'\n hx-swap=\"none\"\n hx-disabled-elt=\"this\">\n <option value=\"draft\">Entwurf<\/option>\n <option value=\"active\">Aktiv<\/option>\n<\/select><\/code><\/pre>\n\n<h2>Controller-Integration<\/h2>\n\n<h3>Basis-Controller Methoden<\/h3>\n<pre><code>\/\/ In Framework\\Controller\n\n\/\/ CSRF validieren (wirft 403 bei Fehler)\n$this->requireCsrf();\n\n\/\/ Erfolg-Alert (via HX-Retarget zu #htmx-messages)\n$this->htmxSuccess('Gespeichert!');\n\n\/\/ Fehler-Alert\n$this->htmxError('Fehler beim Speichern');\n\n\/\/ Redirect (via HX-Redirect Header)\n$this->htmxRedirect('\/items\/' . $id);<\/code><\/pre>\n\n<h3>Beispiel-Controller<\/h3>\n<pre><code>public function update(int $id): void\n{\n $this->requireCsrf();\n \n try {\n $data = $this->getJsonInput();\n $this->useCase->update($id, $data);\n $this->htmxSuccess('Gespeichert');\n } catch (\\Exception $e) {\n $this->htmxError($e->getMessage());\n }\n}<\/code><\/pre>\n\n<h2>Layout-Anforderungen<\/h2>\n\n<h3>Globaler Message-Container<\/h3>\n<p>In <code>layout.php<\/code> muss dieser Container existieren:<\/p>\n<pre><code><main>\n <div id=\"htmx-messages\" class=\"htmx-messages\" aria-live=\"polite\"><\/div>\n <?= $content ?>\n<\/main><\/code><\/pre>\n\n<h3>CSS für HTMX-States<\/h3>\n<pre><code>\/* Message-Container *\/\n.htmx-messages {\n position: fixed;\n top: 80px;\n right: var(--space-lg);\n z-index: 1000;\n max-width: 400px;\n}\n\n\/* Loading-States *\/\n.htmx-indicator { display: none; }\n.htmx-request .htmx-indicator { display: inline; }\n.htmx-request .htmx-content { display: none; }\n\n\/* Disabled während Request *\/\n.htmx-request[hx-disabled-elt] { \n opacity: 0.6; \n pointer-events: none; \n}\n\n\/* Erfolgs-Feedback *\/\n.is-saved {\n border-color: var(--color-success);\n animation: flash-success 0.5s;\n}<\/code><\/pre>\n\n<h2>Enforcement<\/h2>\n\n<h3>Pre-Hook<\/h3>\n<p>Datei: <code>\/var\/www\/tools\/ki-protokoll\/claude-hook\/quality\/pre_rules_htmx.py<\/code><\/p>\n<p>Prüft bei jedem Write\/Edit:<\/p>\n<ul>\n <li>HTMX-Attribute in View-Dateien<\/li>\n <li>CSRF-Token Präsenz<\/li>\n <li>hx-confirm bei Delete<\/li>\n<\/ul>\n\n<h3>Post-Hook<\/h3>\n<p>Warnt bei:<\/p>\n<ul>\n <li>fetch() in View-Dateien<\/li>\n <li>Fehlenden Best-Practices<\/li>\n<\/ul>\n\n<h2>Ausnahmen<\/h2>\n<p>HTMX ist <strong>nicht<\/strong> geeignet für:<\/p>\n<ul>\n <li>Echtzeit-Updates (SSE\/WebSocket nötig)<\/li>\n <li>Komplexe Client-Side-Validierung<\/li>\n <li>Offline-Funktionalität<\/li>\n<\/ul>\n<p>Für diese Fälle: Explizite Ausnahme dokumentieren und minimal JS verwenden.<\/p>\n\n<h2>Verwandte Themen<\/h2>\n<ul>\n <li><a href=\"\/docs\/frontend\/htmx\/patterns\">HTMX Patterns Referenz<\/a> - Alle Patterns im Detail<\/li>\n <li><a href=\"\/docs\/frontend\/htmx\/troubleshooting\">HTMX Troubleshooting<\/a> - Häufige Probleme<\/li>\n <li><a href=\"\/docs\/betrieb\/regeln\">Regeln<\/a> - HTMX statt fetch() Regel<\/li>\n<\/ul>"
}
}
{
"tool_response": [
{
"type": "text",
"text": "{\n \"success\": true,\n \"doc\": {\n \"id\": 145,\n \"parent_id\": 144,\n \"slug\": \"htmx\",\n \"path\": \"\/frontend\/htmx\",\n \"title\": \"HTMX\",\n \"description\": \"HTMX-Patterns und Regeln für das Campus-System\",\n \"content\": \"<nav class=\\\"breadcrumb\\\">\\n <a href=\\\"\/docs\\\">Dokumentation<\/a> » <a href=\\\"\/docs\/frontend\\\">Frontend<\/a> » HTMX\\n<\/nav>\\n\\n<h1>HTMX<\/h1>\\n<p>HTMX ist die <strong>einzige erlaubte Methode<\/strong> für AJAX-Interaktionen im Campus-System.<\/p>\\n\\n<h2>Warum HTMX?<\/h2>\\n<table>\\n <tr><th>Aspekt<\/th><th>HTMX<\/th><th>fetch()\/XHR<\/th><\/tr>\\n <tr><td>CSRF-Enforcement<\/td><td>Automatisch via Contract\/Hook<\/td><td>Manuell, fehleranfällig<\/td><\/tr>\\n <tr><td>Konsistenz<\/td><td>Deklarativ im HTML<\/td><td>Imperativ in JS verstreut<\/td><\/tr>\\n <tr><td>Server-Autorität<\/td><td>Ja<\/td><td>Client-State-Chaos möglich<\/td><\/tr>\\n <tr><td>Progressive Enhancement<\/td><td>Ja<\/td><td>Nein<\/td><\/tr>\\n <tr><td>Debugging<\/td><td>HTML-Attribute sichtbar<\/td><td>DevTools nötig<\/td><\/tr>\\n<\/table>\\n\\n<h2>Contract #14: htmx-patterns<\/h2>\\n<p>Alle HTMX-Regeln sind in Contract #14 definiert und werden durch Pre-Hooks enforced.<\/p>\\n\\n<h3>Kritische Regeln (BLOCK)<\/h3>\\n<table>\\n <tr><th>ID<\/th><th>Regel<\/th><th>Enforcement<\/th><\/tr>\\n <tr><td>HTMX-C1<\/td><td><code>hx-post<\/code> MUSS <code>hx-headers<\/code> mit X-CSRF-TOKEN haben<\/td><td>Pre-Hook BLOCK<\/td><\/tr>\\n <tr><td>HTMX-C2<\/td><td><code>hx-delete<\/code> MUSS <code>hx-headers<\/code> mit X-CSRF-TOKEN haben<\/td><td>Pre-Hook BLOCK<\/td><\/tr>\\n <tr><td>HTMX-C3<\/td><td><code>hx-patch<\/code> MUSS <code>hx-headers<\/code> mit X-CSRF-TOKEN haben<\/td><td>Pre-Hook BLOCK<\/td><\/tr>\\n <tr><td>HTMX-C4<\/td><td><code>hx-delete<\/code> MUSS <code>hx-confirm<\/code> Attribut haben<\/td><td>Pre-Hook BLOCK<\/td><\/tr>\\n <tr><td>HTMX-C5<\/td><td><code>hx-put<\/code> MUSS <code>hx-headers<\/code> mit X-CSRF-TOKEN haben<\/td><td>Pre-Hook BLOCK<\/td><\/tr>\\n<\/table>\\n\\n<h3>Empfohlene Regeln (WARN)<\/h3>\\n<table>\\n <tr><th>ID<\/th><th>Regel<\/th><th>Enforcement<\/th><\/tr>\\n <tr><td>HTMX-R1<\/td><td>Kein fetch() in View-Dateien<\/td><td>Post-Hook WARN<\/td><\/tr>\\n <tr><td>HTMX-R2<\/td><td><code>hx-indicator<\/code> für Loading-States<\/td><td>Dokumentation<\/td><\/tr>\\n <tr><td>HTMX-R3<\/td><td><code>hx-swap<\/code> explizit angeben<\/td><td>Dokumentation<\/td><\/tr>\\n <tr><td>HTMX-R4<\/td><td><code>hx-disabled-elt<\/code> für Button-States<\/td><td>Dokumentation<\/td><\/tr>\\n<\/table>\\n\\n<h2>Standard-Patterns<\/h2>\\n\\n<h3>1. Button mit POST-Action<\/h3>\\n<pre><code><button hx-post=\\\"\/api\/endpoint\\\"\\n hx-headers='{\\\"X-CSRF-TOKEN\\\": \\\"<?= $csrfToken ?>\\\"}'\\n hx-target=\\\"#result\\\"\\n hx-swap=\\\"innerHTML\\\"\\n hx-indicator=\\\"this\\\"\\n hx-disabled-elt=\\\"this\\\">\\n <span class=\\\"htmx-content\\\">Speichern<\/span>\\n <span class=\\\"htmx-indicator\\\">Wird gespeichert...<\/span>\\n<\/button><\/code><\/pre>\\n\\n<h3>2. Delete mit Confirmation<\/h3>\\n<pre><code><button hx-delete=\\\"\/api\/items\/<?= $id ?>\\\"\\n hx-headers='{\\\"X-CSRF-TOKEN\\\": \\\"<?= $csrfToken ?>\\\"}'\\n hx-confirm=\\\"Wirklich löschen?\\\"\\n hx-target=\\\"closest tr\\\"\\n hx-swap=\\\"outerHTML swap:0.3s\\\">\\n Löschen\\n<\/button><\/code><\/pre>\\n\\n<h3>3. Form mit PUT<\/h3>\\n<pre><code><form hx-put=\\\"\/api\/items\/<?= $id ?>\\\"\\n hx-headers='{\\\"X-CSRF-TOKEN\\\": \\\"<?= $csrfToken ?>\\\"}'\\n hx-target=\\\"#form-message\\\"\\n hx-swap=\\\"innerHTML\\\"\\n hx-indicator=\\\"#save-btn\\\"\\n hx-disabled-elt=\\\"#save-btn\\\">\\n <!-- Form fields -->\\n <button type=\\\"submit\\\" id=\\\"save-btn\\\">Speichern<\/button>\\n<\/form>\\n<div id=\\\"form-message\\\"><\/div><\/code><\/pre>\\n\\n<h3>4. Inline-Edit<\/h3>\\n<pre><code><input type=\\\"text\\\" \\n name=\\\"value\\\"\\n value=\\\"<?= htmlspecialchars($value) ?>\\\"\\n hx-post=\\\"\/api\/items\/<?= $id ?>\/field\\\"\\n hx-headers='{\\\"X-CSRF-TOKEN\\\": \\\"<?= $csrfToken ?>\\\"}'\\n hx-trigger=\\\"blur, keyup[key=='Enter']\\\"\\n hx-swap=\\\"none\\\"\\n hx-disabled-elt=\\\"this\\\"\\n hx-on::after-request=\\\"this.classList.toggle('is-saved', event.detail.successful)\\\"><\/code><\/pre>\\n\\n<h3>5. Select mit Auto-Save<\/h3>\\n<pre><code><select name=\\\"status\\\"\\n hx-post=\\\"\/api\/items\/<?= $id ?>\/status\\\"\\n hx-headers='{\\\"X-CSRF-TOKEN\\\": \\\"<?= $csrfToken ?>\\\"}'\\n hx-swap=\\\"none\\\"\\n hx-disabled-elt=\\\"this\\\">\\n <option value=\\\"draft\\\">Entwurf<\/option>\\n <option value=\\\"active\\\">Aktiv<\/option>\\n<\/select><\/code><\/pre>\\n\\n<h2>Controller-Integration<\/h2>\\n\\n<h3>Basis-Controller Methoden<\/h3>\\n<pre><code>\/\/ In Framework\\\\Controller\\n\\n\/\/ CSRF validieren (wirft 403 bei Fehler)\\n$this->requireCsrf();\\n\\n\/\/ Erfolg-Alert (via HX-Retarget zu #htmx-messages)\\n$this->htmxSuccess('Gespeichert!');\\n\\n\/\/ Fehler-Alert\\n$this->htmxError('Fehler beim Speichern');\\n\\n\/\/ Redirect (via HX-Redirect Header)\\n$this->htmxRedirect('\/items\/' . $id);<\/code><\/pre>\\n\\n<h3>Beispiel-Controller<\/h3>\\n<pre><code>public function update(int $id): void\\n{\\n $this->requireCsrf();\\n \\n try {\\n $data = $this->getJsonInput();\\n $this->useCase->update($id, $data);\\n $this->htmxSuccess('Gespeichert');\\n } catch (\\\\Exception $e) {\\n $this->htmxError($e->getMessage());\\n }\\n}<\/code><\/pre>\\n\\n<h2>Layout-Anforderungen<\/h2>\\n\\n<h3>Globaler Message-Container<\/h3>\\n<p>In <code>layout.php<\/code> muss dieser Container existieren:<\/p>\\n<pre><code><main>\\n <div id=\\\"htmx-messages\\\" class=\\\"htmx-messages\\\" aria-live=\\\"polite\\\"><\/div>\\n <?= $content ?>\\n<\/main><\/code><\/pre>\\n\\n<h3>CSS für HTMX-States<\/h3>\\n<pre><code>\/* Message-Container *\/\\n.htmx-messages {\\n position: fixed;\\n top: 80px;\\n right: var(--space-lg);\\n z-index: 1000;\\n max-width: 400px;\\n}\\n\\n\/* Loading-States *\/\\n.htmx-indicator { display: none; }\\n.htmx-request .htmx-indicator { display: inline; }\\n.htmx-request .htmx-content { display: none; }\\n\\n\/* Disabled während Request *\/\\n.htmx-request[hx-disabled-elt] { \\n opacity: 0.6; \\n pointer-events: none; \\n}\\n\\n\/* Erfolgs-Feedback *\/\\n.is-saved {\\n border-color: var(--color-success);\\n animation: flash-success 0.5s;\\n}<\/code><\/pre>\\n\\n<h2>Enforcement<\/h2>\\n\\n<h3>Pre-Hook<\/h3>\\n<p>Datei: <code>\/var\/www\/tools\/ki-protokoll\/claude-hook\/quality\/pre_rules_htmx.py<\/code><\/p>\\n<p>Prüft bei jedem Write\/Edit:<\/p>\\n<ul>\\n <li>HTMX-Attribute in View-Dateien<\/li>\\n <li>CSRF-Token Präsenz<\/li>\\n <li>hx-confirm bei Delete<\/li>\\n<\/ul>\\n\\n<h3>Post-Hook<\/h3>\\n<p>Warnt bei:<\/p>\\n<ul>\\n <li>fetch() in View-Dateien<\/li>\\n <li>Fehlenden Best-Practices<\/li>\\n<\/ul>\\n\\n<h2>Ausnahmen<\/h2>\\n<p>HTMX ist <strong>nicht<\/strong> geeignet für:<\/p>\\n<ul>\\n <li>Echtzeit-Updates (SSE\/WebSocket nötig)<\/li>\\n <li>Komplexe Client-Side-Validierung<\/li>\\n <li>Offline-Funktionalität<\/li>\\n<\/ul>\\n<p>Für diese Fälle: Explizite Ausnahme dokumentieren und minimal JS verwenden.<\/p>\\n\\n<h2>Verwandte Themen<\/h2>\\n<ul>\\n <li><a href=\\\"\/docs\/frontend\/htmx\/patterns\\\">HTMX Patterns Referenz<\/a> - Alle Patterns im Detail<\/li>\\n <li><a href=\\\"\/docs\/frontend\/htmx\/troubleshooting\\\">HTMX Troubleshooting<\/a> - Häufige Probleme<\/li>\\n <li><a href=\\\"\/docs\/betrieb\/regeln\\\">Regeln<\/a> - HTMX statt fetch() Regel<\/li>\\n<\/ul>\",\n \"status\": \"published\",\n \"sort_order\": 1,\n \"depth\": 1,\n \"created_at\": \"2025-12-27T12:23:53\",\n \"updated_at\": \"2025-12-27T15:40:04\"\n },\n \"message\": \"Document #145 updated\"\n}"
}
]
}