kantarciandClaude Opus 5 ee446f1ea1 Einwilligung, die tatsächlich zurückhält, und Pflichtseiten
Ein Hinweis, der nur fragt und sonst nichts ändert, ist Theater. Deshalb zwei
Hälften, und die zweite ist die wichtigere.

Die Frage: serverseitig gerendert, per Formular beantwortet, ohne JavaScript -
die öffentlichen Seiten laufen mit script-src 'none', und ein Banner mit
Skript wäre das eine, was diese Regel bricht. "Alle akzeptieren" und "Nur
notwendige" sind dieselbe Art Knopf, gleich groß, nebeneinander. Die
Entscheidung steht in einem eigenen Cookie: Fassung der Frage, gewährte
Gruppen, Zeitpunkt. Keine Kennung, kein Serverabgleich, ein halbes Jahr. Kein
CSRF-Token, absichtlich: die Anfrage ändert nichts auf dem Server, und ein
Token bräuchte für jeden Besucher eine Sitzung - genau das, was ein
Einwilligungshinweis vermeiden soll. Geprüft wird stattdessen das
Rücksprungziel.

Das Zurückhalten: der neue Block "Externer Inhalt" (Dokumentschema v14) lädt
ohne Einwilligung nichts - kein iframe, keine Adresse im Markup, frame-src
'none'. Der Platzhalter nennt den Anbieter; sein Knopf gewährt genau diese
Gruppe und nimmt die vorher gewährten mit. Erst danach kommt der Host in die
Sicherheitsrichtlinie, und nur dieser. Im Editor bleibt es immer ein
Platzhalter.

Datenschutz und Impressum sind keine Einstellung mehr: fehlen sie, warnt die
Verwaltung und legt sie auf Knopfdruck als Gerüst an, mit NOCH AUSZUFÜLLEN an
jeder Pflichtangabe. Den Text schreibt das CMS nicht - das ist eine rechtliche
Aussage über eine Firma. Verlinkt werden beide aus dem Template, nicht aus dem
Fußbereich: ein Pflichtlink, den man löschen kann, ist keiner.

Dazu der Fehler, den Umut im Screenshot gesehen hat: die Wortmarke stand als
Buchstabenkolonne in einem 60 Pixel breiten Kasten. .site-header war noch ein
Flexcontainer aus der Zeit des handgeschriebenen Markups und quetschte die
Sektion zusammen, und design.css band jede Designklasse an #main - wo Kopf-
und Fußbereich seit ADR 026 nicht mehr liegen. Beides behoben.

Neu im Ausbauplan: Statistik (serverseitige, wiedererkennungsfreie Zählung,
die deshalb keine Einwilligung braucht), Inhalte und Ladeverhalten prüfen
(Blättern überall, minimal laden, Ladebudget), Installer (Schritt für Schritt
im Browser, Migration inklusive).

245 PHP-Tests / 976 Assertions unter PHP 8.2.12 und 8.4.22. Der Browsertest
fand zwei Fehler von mir: grauer Text auf dunklem Fußbereich mit 2,24:1, und
das fixierte Banner verdeckte den Einwilligungsknopf am Seitenende.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 19:27:41 +02:00
2026-09-12 18:36:50 +02:00
2026-09-12 18:36:50 +02:00
2026-09-12 18:36:50 +02:00
2026-09-12 18:36:50 +02:00

KantSites

Lokaler CMS-Prototyp für PHP-Webhosting mit erstem visuellen Editor. Symfony 7.4, Twig, Doctrine DBAL/Migrations; SQLite lokal, MySQL/MariaDB als Hostingziel. Drei gespeicherte Beispielseiten werden ohne JavaScript als HTML ausgeliefert. Anmeldung, geschützte Bearbeitung und getrennte Veröffentlichung sind implementiert; weitere Layoutwerkzeuge folgen.

Die übernommenen Originaldokumente sind AGENTS.md und ENTWICKLUNGSPLAN.md. Den tatsächlichen Stand enthält docs/STATUS.md, Entscheidungen und Datenmodell stehen in docs/ARCHITECTURE.md.

Lokal starten

Voraussetzungen: PHP ab 8.2 mit Composer 2, PDO SQLite, Ctype, Iconv, Session, XML und GD mit WebP-Unterstützung. EXIF wird für die automatische Ausrichtung von JPEG-Fotos empfohlen. Für Tests zusätzlich die von composer install geprüften Erweiterungen, insbesondere DOM, XMLWriter und Mbstring. Für Hosting eine aktuell gepflegte PHP-Patchversion verwenden. Node 24 wird für Browserprüfungen und das Generieren der Design-CSS gebraucht, nicht im Hostingbetrieb.

composer install
php bin/setup.php
php vendor/bin/doctrine-migrations migrate --no-interaction
php bin/console cms:seed-demo
php -d upload_max_filesize=8M -d post_max_size=10M -d memory_limit=256M -S 127.0.0.1:8080 -t public bin/dev-router.php

Danach http://127.0.0.1:8080/ öffnen. Der Routerskript-Parameter ist nicht optional: der eingebaute PHP-Server liefert vorhandene Dateien selbst aus und antwortet für jeden fehlenden Pfad mit Dateiendung mit 404, sodass /sitemap.xml, /robots.txt, /llms.txt und /feed.xml den Frontcontroller nie erreichen. Auf echtem Hosting erledigt das public/.htaccess; bin/dev-router.php bildet dasselbe lokal nach. Unter Windows hier vorhanden: C:\xampp\php\php.exe (8.2.12) und C:\php84\php.exe (8.4.22). Die Befehle verwenden die PHP-Version im PATH; alternativ den vollständigen Pfad einsetzen. Diese vorhandenen Patchstände sind kein empfohlenes Produktionsimage.

bin/setup.php erzeugt ein zufälliges lokales Secret und var/; bestehende .env.local bleibt erhalten. Die Datenbank liegt in var/cms.db. Wiederholtes Seeding erhält existierende Seiten einschließlich ihrer Bearbeitungen. Es gibt keinen öffentlichen Installer und keine Standardzugangsdaten. Editor-Endpunkte benötigen Anmeldung, Berechtigung und bei POST einen CSRF-Token.

Anmelden und bearbeiten

Für eine neue Installation im interaktiven Terminal ein Konto anlegen:

php bin/console cms:user:create meinname

Das Passwort wird verdeckt zweimal abgefragt (14–72 Bytes). Bestehende Benutzer werden nicht überschrieben. Optional --role=editor für Entwürfe oder --role=publisher für Entwürfe plus Veröffentlichung; Standard ist admin. Es gibt noch keine Benutzerverwaltung oder Passwortänderung im Browser. In der aktuellen lokalen Installation wurde auf Nutzerwunsch bereits der Administrator umut angelegt und angemeldet; keine Zugangsdaten sind im Repository abgelegt.

Unter http://127.0.0.1:8080/admin eine Seite auswählen. Links Blöcke hinzufügen/auswählen, in der Mitte die Vorschau, rechts Eigenschaften. Die Auswahl ist zwischen Strukturbaum und Vorschau synchron. Sektion, Zeile, Spalte, Überschrift, Text, Bild, Button und Galerie sind vorhanden. Bilder können aus der Mediathek oder über vorhandene lokale/HTTPS-Adressen eingebunden werden.

Blöcke per Drag-and-drop verschieben: auf einen Container ziehen, um hineinzuverschieben; auf einen Text-/Bild-/Linkblock ziehen, um davor einzufügen. Alternativ unten am Strukturbaum die Schaltflächen für Auf/Ab, Verschachteln und Herausheben verwenden. Duplizieren vergibt neue Block-IDs und wandelt eine kopierte H1 in H2 um. Löschen lässt sich rückgängig machen. Jede speicherbare Seite benötigt genau eine H1.

Undo/Redo gilt für die lokale Bearbeitung, Strg+S speichert den Entwurf. Strg+Z/Strg+Umschalt+Z gelten außerhalb der Texteingaben für das Dokument; Texteingaben behalten ihr natives Undo. Erst speichern, dann separat veröffentlichen. Die Bestätigungsdialoge unterstützen Escape und Fokus-Rückkehr. Reine Redakteure können nicht veröffentlichen.

Ein Speicherkonflikt überschreibt nichts: lokale Änderungen als JSON sichern und den Serverstand bewusst neu laden. Auch Netzwerk-/Sitzungsfehler lassen den lokalen Stand erhalten. Die Vorschau behält bei ungültigen Eingaben die letzte gültige Ausgabe.

Rechts zwischen Inhalt und Design wechseln. Unter Design je nach Block Abstände, Schriftgröße/-stärke, Zeilenhöhe, Ausrichtung, Spalten und Ecken wählen. Oben Desktop/Tablet/Mobil bestimmt das bearbeitete Gerät: Desktop ist die Basis, Tablet überschreibt bis 1024 px, Mobil bis 650 px. „Übernehmen“ entfernt einen eigenen Wert und stellt die Vererbung wieder her. Gerätewerte lassen sich gemeinsam zurücksetzen und rückgängig machen. Farben und Inhaltsbreite einer Sektion stehen unter Inhalt.

Die Vorschau rendert mit echten 1240/768/390 px Layoutbreite und passt sich durch Skalierung an den verfügbaren Platz an. Links lassen sich fertige Intro-, Leistungs- und Kontaktabschnitte einfügen. Der Werkzeugkasten kann für mehr Platz geschlossen werden. Die Struktursuche findet Text oder Elementtypen und zeigt den Pfad zum Treffer; Dreiecke klappen Teilbäume ein. Oberhalb der Vorschau führen die Pfadschaltflächen direkt zum übergeordneten Element.

Produktionsmodus lokal prüfen

composer build
$env:APP_ENV = 'prod'
$env:APP_DEBUG = '0'
php -d upload_max_filesize=8M -d post_max_size=10M -d memory_limit=256M -S 127.0.0.1:8080 -t public bin/dev-router.php

Unter Linux dieselben PHP-Argumente mit vorangestelltem APP_ENV=prod APP_DEBUG=0 verwenden. Vorher eine laufende Instanz auf diesem Port beenden. Zum Entwickeln APP_ENV=dev und APP_DEBUG=1 setzen. Debug-Seiten senden absichtlich X-Robots-Tag: noindex; Audits laufen im Produktionsmodus. Der eingebaute PHP-Server bleibt ein lokaler Entwicklungsserver.

Medien, Galerien und Effekte

Links im Werkzeugkasten Medienverwaltung öffnen oder auf der Seitenübersicht Medienverwaltung wählen. JPEG/PNG/WebP hochladen, Titel und Alternativtext bearbeiten und speichern. Bilder lassen sich suchen, archivieren und wiederherstellen. Die Dateien werden als optimierte WebP-Varianten gespeichert; Originaldateien werden nicht aufgehoben. Uploadgrenzen: 8 MB, 12 Megapixel und 8000 px Kantenlänge; Hostinglimits können niedriger sein. Bild-URLs sind öffentlich erreichbar, auch wenn sie noch in keinem veröffentlichten Inhalt verwendet werden.

Für ein einzelnes Bild Bild aus Mediathek wählen anklicken. Für eine Galerie den Block Galerie einfügen und Galeriebilder auswählen öffnen. Mehrere Bilder markieren, Alt-Texte speichern oder die dekorative Verwendung wählen und Auswahl übernehmen. Im Strukturbaum einzelne Bilder auswählen, beschriften und sortieren; Reihenfolge und Einfügen lassen sich rückgängig machen. Unter Design Spaltenzahl und Abstände pro Gerät einstellen.

Unter Design → Effekte Schatten, Hover-Anheben/Bildzoom und Einblendung beim Laden wählen. Effekte gelten für alle Geräte; bei aktivierter Bewegungsreduktion werden Animationen abgeschaltet. Die öffentliche Seite benötigt dafür kein JavaScript. Lightbox, Slideshow, Video/PDF-Upload und Bildzuschnitt sind noch nicht enthalten.

Medien liegen standardmäßig in var/media; mit MEDIA_DIRECTORY lässt sich ein absoluter Ordner außerhalb von public konfigurieren. Er muss für PHP beschreibbar sein. Auf dem Hosting upload_max_filesize=8M, post_max_size=10M und ausreichend Arbeitsspeicher (lokal 256M) einstellen, soweit der Tarif dies erlaubt. Datenbank und Medienordner gemeinsam sichern. Archivieren erhält Bild-URLs; es ist keine Dateilöschung.

Prüfen

composer validate --strict
composer lint
composer test
php bin/console lint:twig templates
php bin/console lint:yaml config
php bin/console lint:container
composer audit
composer build
npm.cmd ci
npx.cmd playwright install chromium
npm.cmd run test:browser
npm.cmd test
npm.cmd run test:editor
npm.cmd run test:editor -- --audit
npm.cmd run audit

Unter Linux/macOS npm und npx ohne .cmd; in CI npx playwright install --with-deps chromium. test:browser und audit benötigen den laufenden lokalen Produktionsmodus auf Port 8080. Ein anderes Ziel lässt sich über CMS_URL konfigurieren. test:editor startet einen eigenen PHP-Prozess auf einem freien Port mit isolierter Datenbank und zufälligem Testkonto; es ändert keine echten Seiten oder Benutzer. PHP_BINARY kann dafür einen alternativen PHP-Pfad angeben. Testdaten bleiben unter var/browser-tests, Berichte/Screenshots unter reports/. Das Skript erneuert zuvor den Produktionscache.

composer format formatiert PHP. composer build wärmt den Symfony-Produktionscache; öffentliche CSS-Dateien sind direkt auslieferbar, es ist kein Frontend-Bundler nötig. Bei Änderungen an public/assets/design-tokens.json einmal npm.cmd run build:design ausführen und die erzeugte CSS-Datei mitliefern; Node ist auf dem Hosting nicht erforderlich. Nach Änderungen an Produktionskonfiguration/Templates php bin/console cache:clear --env=prod --no-debug ausführen. Falls lokale Tests alte Templates verwenden, vor PHPUnit auch php bin/console cache:clear --env=test --no-debug ausführen.

Das Lighthouse-Skript misst die Startseite dreimal je Profil und prüft die Mediane gegen die Projektziele. test:editor -- --audit prüft die im isolierten Editortest gestaltete v3-Seite mit Abschnittsvorlage, Galerie, tatsächlichen Bildvarianten und Effekten; Berichte stehen unter reports/lighthouse-editor. Uploads und Datenbank des Tests liegen getrennt unter var/browser-tests. Diese kleinen Prototypseiten ersetzen nicht die spätere Referenzsuite mit Kundeninhalten, Fotos, Beitrag und Formular. Messgrenzen und Ergebnisse: docs/QUALITY.md.

Inhalte und Entwicklung

Die Formate v1/v2/v3 und erlaubten Blöcke stehen in src/Content/DocumentValidator.php, Gestaltungstokens in public/assets/design-tokens.json, Entwicklungsinhalte in src/Content/DemoContent.php. Designwerte erfordern mindestens v2, Medien/Galerien/Effekte v3. Die erste entsprechende Aktion migriert den lokalen Entwurf erhaltend; erst Speichern schreibt eine neue Revision. Bestehende v1/v2-Seiten bleiben lesbar. Migrations- und Rückweg: ADR 008/009 in docs/ARCHITECTURE.md. PageRepository stellt saveDraft, publish und findPublished bereit. Speichern und Publizieren erfordern die erwartete Seitenversion; veraltete Zugriffe brechen mit StaleWrite ab.

Ein JSON-Dokument lässt sich zusätzlich lokal über php bin/console cms:save-draft PAGE_ID PFAD_ZUR_DATEI ERWARTETE_VERSION speichern. Der Befehl gibt die neue Revisions-ID aus. Die redaktionelle Bearbeitung und Veröffentlichung erfolgen jetzt über den geschützten Editor.

PHP-Webhosting

Anforderungen vor dem Pilotbetrieb beim Anbieter bestätigen:

  • Gepflegte PHP-Version ab 8.2, PDO MySQL und die Composer-Plattformanforderungen.
  • MySQL 8 oder kompatible MariaDB; tatsächliche Version und Berechtigungen noch überprüfen.
  • Domain-Dokumentenstamm muss auf public/ zeigen. vendor/, var/, Konfiguration und Secrets gehören außerhalb des öffentlichen Verzeichnisses.
  • Apache mit Rewrite-Unterstützung für public/.htaccess oder entsprechende FastCGI/Nginx-Konfiguration.
  • Schreibzugriff für PHP auf var/, HTTPS und eine Möglichkeit, Migrationen/Cache-Kommandos kontrolliert auszuführen.

Serverkonfiguration über echte Umgebungsvariablen oder eine nicht öffentliche .env.local: APP_ENV=prod, APP_DEBUG=0, eigenes zufälliges APP_SECRET, SITE_ORIGIN=https://eigene-domain.example und DATABASE_URL=mysql://USER:URL_ENCODED_PASSWORD@HOST:3306/DATABASE?charset=utf8mb4. Das ist eine Vorlage, keine funktionierende Zugangskonfiguration.

Deployment später mit composer install --no-dev --optimize-autoloader, Backup, Migration und Cacheaufbau. Composer darf auf einem geeigneten Build-Rechner laufen, sodass das Hosting weder Node noch Composer benötigt; CLI-Zugriff oder ein verlässlich dokumentierter Deploymentweg für Datenbankmigrationen bleibt zu klären. Keine Installation ins öffentlich erreichbare Projektstammverzeichnis.

Ein Livegang, Hostzugriff, Restore-Test und Produktionsfreigabe sind nicht erfolgt. Bei bestehenden Installationen vor dem Update Datenbank und Medien sichern und php vendor/bin/doctrine-migrations migrate --no-interaction ausführen. Migration 20260912000200 ergänzt Benutzer, 20260912000300 die Medientabelle; beide verändern keine Seitendokumente. Migration 20260912001100 ergänzt drei Datumsspalten an cms_user (drei ADD COLUMN, kein Tabellenneubau). Benutzerverwaltung und Passwortänderung gibt es jetzt in der Oberfläche unter „Benutzer“ und „Mein Konto“; php bin/console cms:user:create bleibt der Weg, wenn kein Konto mehr funktioniert. Der Abgleich mit der Pilotwebsite bleibt der nächste Schritt. Wie ein Update später über einen Git-Tag laufen soll, steht als Plan in docs/UPDATE.md – gebaut ist davon noch nichts.

S
Description
No description provided
Readme
5.1 MiB
0 Stars 1 Watchers 0 Forks
1.36.1
Latest
2026-10-14 10:20:48 +00:00
Languages
PHP 69%
JavaScript 19.5%
Twig 8.1%
CSS 3.2%
Shell 0.2%