Rueckmeldung 22.08.2026 mit Bildschirmfoto aus dem eigenen Testzugang:
"die seite soll jetzt schon bitte richtig krass sein und hoch profissionel,
auch sehr detailliert."
Zwei Luecken, beide geschlossen:
1) Projekte liessen sich nur ueber die Schnittstelle anlegen. Jetzt in der
Verwaltung: pro Kunde ein "+ Projekt" mit Titel, Paket, Preis,
Richttermin und naechstem Schritt. Bewusst als Einblendung direkt bei
der Kundenzeile statt als eigene Seite -- man legt ein Projekt IMMER
fuer einen bestimmten Kunden an, nie im luftleeren Raum. Der Kundenname
steht deshalb gross im Formular, damit es nicht versehentlich dem
Falschen angehaengt wird.
Die 30 % Anzahlung wird beim Tippen live mitgerechnet. Sie wird zwar
serverseitig berechnet, aber wer sie beim Eintippen sieht, merkt eine
falsche Null sofort -- und nicht erst, wenn der Kunde ueberweisen soll.
2) Der leere Zustand im Portal war ein einziger Satz. Das ist eine
verpasste Gelegenheit: Wer dort zum ersten Mal landet, hat gerade sein
Passwort gesetzt und weiss noch nicht, was ihn erwartet -- genau dann
entscheidet sich, ob die Seite souveraen wirkt oder unfertig. Jetzt
zeigt er in vier Punkten, WAS gleich hier stehen wird (Projektstand,
wer am Zug ist, Dateien und Nachrichten, Ideen jederzeit) und schliesst
mit der Zusicherung, dass nichts zu tun ist. Fuenfsprachig.
45/45 Handy-Abnahme, i18n vollstaendig.
Co-Authored-By: Claude Opus 5 <[email protected]>
Vier Ansichten in einer Seite: Anmeldung, Passwort festlegen ueber den
Einladungslink, Uebersicht, Projektdetail. 71 Textbausteine in fuenf
Sprachen.
Korrektur an einer frueheren Entscheidung: Ich hatte das Portal als "nur
Deutsch" eingestuft wie die Verwaltung. Denkfehler -- die Verwaltung
nutzen Dogfather und VanVan, das PORTAL nutzen Kunden, und die koennen
Franzosen oder Portugiesen sein. Jetzt fuenfsprachig, und die Sprache des
Kunden wird bei der Anmeldung automatisch uebernommen.
Gestaltungsentscheidungen:
* Eine Phasenleiste zeigt auf einen Blick, wo das Projekt steht. Das ist
die haeufigste Frage ueberhaupt und der Grund, warum Kunden anrufen.
Bei pausierten oder abgebrochenen Projekten wird KEINE Leiste gezeigt --
ein Fortschrittsbalken waere dort irrefuehrend.
* Eine Marke sagt, wer gerade am Zug ist ("Wir warten auf dich" /
"Dogfather ist dran"). Das beendet die haeufigste Unklarheit im
Projektverlauf.
* Offene Zahlungen stehen ganz oben und in Gold -- das Einzige, was den
Kunden wirklich zum Handeln auffordert.
* Rueckfrage nur beim ANNEHMEN eines Zusatzangebots, nicht beim Ablehnen.
Annehmen erzeugt eine Zahlungspflicht, Ablehnen ist folgenlos.
* Abgelaufene Sitzung fuehrt zur Anmeldung mit klarer Ansage statt zu
einer leeren Seite, die wie "du hast keine Projekte" aussaehe.
* Der Einladungslink wird nach Gebrauch aus der Adresszeile entfernt --
er ist verbraucht und hat in der Chronik nichts verloren.
* Die Zahlungsknoepfe sagen ehrlich, dass PayPal noch eingerichtet wird,
statt so zu tun als wuerde etwas passieren.
Pruefskript zweimal geschaerft, beide Male waren es Fehlalarme:
* Die Heuristik fuer Nachschlagetabellen hielt gewoehnliche Woerter wie
"abnahme" und "uebergeben" fuer Woerterbuch-Schluessel. Jetzt muss ein
Unterstrich im Namen sein, so wie bei allen echten Schluesseln.
* Eine Ueberschrift gilt jetzt auch als uebersetzt, wenn die Uebersetzung
INNEN sitzt (fester Teil + dynamischer Teil).
i18n vollstaendig, 45/45 Handy-Abnahme.
Co-Authored-By: Claude Opus 5 <[email protected]>
Rueckmeldung 22.08.2026: "ich will nicht dass man die hin und her
schieben muss man soll die alle sehen aber nicht schieben muessen."
Richtig, und aus zwei Gruenden: Eine Wischleiste verbirgt, DASS es noch
mehr gibt -- was rechts aus dem Bild ragt, existiert fuer die meisten
Menschen schlicht nicht. Dazu kam ein haesslicher Scrollbalken quer ueber
die Seite. Jetzt brechen die Knoepfe um, alle fuenf sind auf einen Blick
da, auch bei 320px.
Der Text in den Knoepfen darf dabei mitbrechen (white-space: normal) --
ohne das sprengt ein langer Name wie "Buchhaltungs- &
Steuerverwaltungsseiten" auf schmalen Bildschirmen die Zeile und der
waagerechte Ueberlauf waere durch die Hintertuer zurueck.
Dabei mitgefunden: "hyphens: auto" auf Ueberschriften. Auf dem Handy
stand dadurch "Alles, was vorher ge-klaert sein sollte". Der Browser
trennt damit nach Silben, auch wenn ueberhaupt kein Platzproblem
besteht. In Fliesstext ist das ein Gewinn, in grossen Ueberschriften
sieht es billig aus -- und genau die sind das Erste, was jemand sieht.
overflow-wrap: break-word bleibt und faengt echte Ueberlaeufe weiterhin ab.
Pruefskript: die Sprungmarken-Leisten waren als "absichtlich scrollbar"
von der Ueberlaufpruefung ausgenommen. Diese Ausnahme ist raus -- sonst
wuerde ein zurueckkehrender Ueberlauf dort nie auffallen. 45/45 weiterhin
sauber.
Co-Authored-By: Claude Opus 5 <[email protected]>
Masterplan S.10 "Projektanfrage ohne Informationsverlust" umgesetzt.
End-to-End gegen die echte Datenbank belegt: Anfrage A-2608-0002 liegt drin.
38/38 Browsertests, 45/45 Handy-Abnahme.
Aufbau: 4 Schritte + Zusammenfassung + Dankeseite.
- Zwischenspeicherung nach jedem Tastendruck. Geschlossener Tab, leerer
Akku oder versehentliches Zurueck kosten keine Arbeit. Entwuerfe
verfallen nach 30 Tagen -- ein halbes Jahr alter Entwurf verwirrt mehr
als er hilft.
- Folgefragen erscheinen nur passend zur Auswahl und werden beim
Zurueckwechseln NICHT mitgeschickt, sonst landen alte Shop-Antworten in
einer Onepager-Anfrage.
- Die Zusammenfassung wird aus den Feldern gelesen, nicht aus einem
nebenher gepflegten Objekt -- sie kann dadurch nie etwas anderes
behaupten als das, was tatsaechlich abgeschickt wird.
- Telefon wird zur Pflicht, sobald "Per Telefon" gewaehlt ist. Ein Wunsch,
der nicht erfuellbar ist, ist schlimmer als eine Pflichtangabe.
Drei Fehler, die erst der Test gefunden hat:
1. Der "Zurueck"-Knopf stand auch auf Schritt 1 da. Ursache: das
hidden-Attribut wird nur ueber "display:none" umgesetzt und verliert
gegen jedes eigene display -- und Knoepfe sind inline-flex. Zentral
behoben ueber ".wd [hidden] { display:none !important }".
2. Nach erfolgreichem Absenden legte zeigeSeite() den geloeschten Entwurf
sofort wieder an. Beim naechsten Besuch haette eine bereits gesendete
Anfrage erneut im Formular gestanden.
3. Der Server meldet bei Spamverdacht bewusst Erfolg ohne Nummer. Ein
echter Mensch, der zufaellig sehr schnell war, haette eine Dankeseite
mit "—" gesehen und auf eine Antwort gewartet, die nie kommt. Jetzt
ein ehrlicher Hinweis mit zweitem Weg, und der Entwurf bleibt erhalten.
Pruefskripte geschaerft:
- i18n-Pruefung liest jetzt auch assets/js/wd-<seite>.js, sonst meldet sie
reihenweise "unbenutzt" fuer Schluessel, die aus dem Seitenskript kommen.
- Handy-Abnahme ueberspringt absichtlich unsichtbare Eingabefelder
(Auswahlkacheln, Honigtopf). Fehlalarme sind das Ende jeder Pruefung,
weil man sie irgendwann pauschal ignoriert.
Co-Authored-By: Claude Opus 5 <[email protected]>
Gemeldet 22.08.2026 mit Bildschirmfoto: "immer noch so" -- das Logo im
Marken-Intro stand weiterhin hochkant gestreckt da, obwohl die Korrektur
(height:auto gegen die height-Attribute) laengst live war.
Ursache war NICHT die Korrektur, sondern mein eigener Service Worker. Er
lief fuer /assets/ als "stale-while-revalidate": die gespeicherte Fassung
geht sofort raus, im Hintergrund wird eine frische geholt. Das ist schnell
-- bedeutet aber, dass jede Aenderung an CSS oder JavaScript beim ersten
Aufruf unsichtbar bleibt und erst beim zweiten wirkt. Ein behobener Fehler
sieht dadurch aus wie ein nicht behobener. Die unangenehmste Sorte.
Nachgemessen ist das Logo jetzt 160x161px bei einem natuerlichen
Verhaeltnis von 472x476 -- also unverzerrt. Vorher erzwang das Attribut
height="476" bei 160px Breite ein Verhaeltnis von 0,34 statt 0,99, genau
das lange Gesicht auf dem Bildschirmfoto.
Behoben:
- Stilvorlagen und Skripte laufen jetzt "Netz zuerst", Zwischenspeicher
nur als Notfallnetz. Richtigkeit vor Millisekunden.
- Bilder und Symbole bleiben beim schnellen Weg -- die aendern sich
praktisch nie und bekaemen sonst einen neuen Dateinamen.
- CACHE_NAME auf v2 gesetzt, damit der alte Speicher beim naechsten Start
vollstaendig weggeworfen wird.
- Versionsnummer an allen CSS/JS-Verweisen hochgesetzt, damit es sich auch
ohne Service Worker sofort selbst heilt.
Ausserdem: Woerterbuch fuer das Anfrageformular, 101 Textbausteine in fuenf
Sprachen (vier Schritte, Zusammenfassung, Fehlermeldungen).
Co-Authored-By: Claude Opus 5 <[email protected]>
Rueckmeldung 22.08.2026 per Bildschirmfoto: "die sollen alle gleich
aussehen und nicht einer groesser oder kleiner" und "ich will nicht soooo
viel abstand".
1) Verzerrte, ungleich hohe Projektbilder
Nachgemessen: 576px breit, aber 750px bzw. 696px hoch -- also hochkant
gestreckt und unterschiedlich, obwohl im CSS sauber "aspect-ratio:
16/10" stand. Ursache: die width/height-Attribute im HTML (die dort
bewusst stehen, damit der Browser vor dem Laden den Platz reserviert
und die Seite nicht springt) wirken wie eine CSS-Hoehe und schlagen
aspect-ratio. Fix zentral ueber ".wd img[width][height] { height:
auto }" statt in jeder einzelnen Regel -- so kann es bei einem neuen
Bild nicht vergessen werden.
Jetzt beide 576x360, Karten beide 853px hoch.
2) Zu viel Leerraum
.wd-abschnitt hatte 100,8px oben UND unten, also gut 200px zwischen
zwei Abschnitten. Halbiert auf 57,6px, Hero von 78svh auf 68svh.
Seitenlaenge dadurch 8798px -> 7089px bei gleichem Inhalt.
3) Zwei neue Dauerpruefungen in pruefe-webdesign-handy.mjs, damit genau
diese beiden Fehlerarten nicht wieder per Bildschirmfoto auffallen
muessen:
- verzerrte Bilder (gewuenschtes vs. tatsaechlich gerendertes
Seitenverhaeltnis, 2 % Toleranz)
- ungleich hohe Karten innerhalb EINER Rasterzeile
40/40 Abnahme weiterhin sauber.
Co-Authored-By: Claude Opus 5 <[email protected]>
Zwei Rueckmeldungen vom 22.08.2026, beide behoben und mit Tests abgesichert.
1) "das sieht nicht gut aus" (Bildschirmfoto des Hauptknopfs)
Ursache: ".wd a" ist Klasse+Element und damit spezifischer als die reine
Knopfklasse ".wd-btn--haupt". Die Textfarbe des Knopfs wurde dadurch
ueberstimmt -- hellblaue Schrift auf hellblauem Grund, praktisch
unlesbar. Derselbe Spezifitaetsfehler wie zuvor bei den Namen auf der
Zugangswand. Fix: ".wd a:not(.wd-btn)" plus zweistufig geschriebene
Knopfregeln, damit das nicht wieder passieren kann.
2) "das sieht lang gezogen aus"
Die Pillenform (border-radius 999px) laesst breite Knoepfe
auseinandergezogen wirken, weil der Radius optisch mit der Breite
mitwaechst. Jetzt fester Radius von 14px -- gleiche Form bei jeder
Breite, ruhiger und hochwertiger.
3) "ich will das ich jedes mal den code gefragt werde wenn man die seite
zu macht"
Das Sitzungs-Cookie allein reicht dafuer nicht: Browser stellen genau
solche Cookies beim Wiederherstellen von Tabs zurueck ("Dort
fortfahren, wo du aufgehoert hast"), man landet dann ohne Codeabfrage
wieder mitten in der Seite. Zusaetzlich jetzt eine Sitzungsmarke im
sessionStorage, die beim echten Schliessen verschwindet. Fehlt sie bei
vorhandenem Cookie, wird die Sitzung serverseitig beendet und zur
Zugangswand geleitet. Token-Notbremse von 24 auf 8 Stunden gesenkt.
13/13 Tests im echten Browser, inklusive Schutz vor Endlosschleife.
DEPLOY.md: zwei Checkouts auf dem Server dokumentiert (/home/dogiweb und
/home/dogiintern) und der Vorfall, dass /webdesign nach dem Pull kurz ohne
Zugangsschutz erreichbar war, weil der Dienstneustart fehlte.
Co-Authored-By: Claude Opus 5 <[email protected]>
Umsetzung des "Website Masterplan" (16 Seiten) unter /webdesign.
Zugangsschutz mit EIGENER Schranke (server/webdesign-gate.js) statt gate.js:
gate.js laesst seit dem oeffentlichen Start am 21.08.2026 jeden durch, weil
die Pruefung auf SITE_PUBLIC_LAUNCH_AT als allererste Zeile steht. Haette man
/webdesign dahintergehaengt, waere der ausdruecklich nicht-oeffentliche Bereich
inklusive Preisen und spaeteren Kundendaten ab der ersten Sekunde fuer jeden
lesbar gewesen. Eigenes Sitzungs-Cookie, bereich="webdesign" im Token, damit
ein gueltiges Universe-Cookie hier NICHT gilt. 37/37 Tests.
Sieben oeffentliche Seiten in fuenf Sprachen (de, de-CH mit echtem Dialekt, en,
fr, pt). Preise, Zeitrahmen, Paketnamen und die 30-%-Regel stehen an genau
EINER Stelle in wd-core.js -- der Masterplan verlangt "ueberall
widerspruchsfrei", und vier Kopien laufen bei der ersten Preisaenderung
auseinander.
Als App installierbar auf Handy und PC. Der Service Worker speichert bewusst
KEINE HTML-Seite zwischen: nach dem Abmelden wuerden sonst geschuetzte Seiten
weiter ausgeliefert, ohne dass der Server je gefragt wird. 18/18 Tests.
Handy-Abnahme ueber alle Seiten in fuenf Breiten (320-1440) und fuenf Sprachen:
40/40. Der Test fand 35 echte Fehler (Touch-Ziele unter 44px), behoben im
Designsystem statt einzeln pro Seite.
PayPal (Wunsch 22.08.2026 "sofort auf meinem paypal"): Orders API mit
intent=CAPTURE, also sofortiger Einzug statt blosser Reservierung. Gebuehr und
Nettobetrag getrennt gespeichert. Betraege durchgehend als Ganzzahl in Cent.
Gefaelschte Webhooks werden abgewiesen. Fail closed solange Zugangsdaten
fehlen. 28/28 Tests gegen einen nachgebauten PayPal-Server.
Datenbank: 15 Tabellen mit Praefix wd_, fachlich vollstaendig vom Universe
getrennt.
Co-Authored-By: Claude Opus 5 <[email protected]>
Beim Abgleich zwischen Rechner und Netcup-Server am 22.08.2026 aufgefallen:
20 Bilddateien wurden live von mehreren Seiten benutzt (bewerben-modi.html,
links.html, medien-casper.html, medien-hasidog.html, supporter.html,
stimmen.html u.a.), lagen aber in keiner Git-Ablage -- nur auf diesem
Rechner und auf dem Server. Waeren beide verloren gegangen, waeren diese
Seiten ohne Hintergrund/Avatare dagestanden.
Vor dem Hinzufuegen jede Datei per Pruefsumme gegen den Server abgeglichen
-- alle identisch, kein abweichender Stand wird hier verdeckt.
dogfather-universe-app.ico ist aktuell nirgends verlinkt (vermutlich ein
nie eingebauter Favicon-Entwurf), trotzdem mit gesichert statt verworfen.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Report per Foto: beim Tippen auf "DE" im Handy-Menue erschien das
Sprachfenster halb links ausserhalb des Bildschirms, man konnte keine
Sprache mehr lesen oder treffen.
Ursache: Die Handy-Regel, die alle Aufklapp-Fenster auf statische Position
und volle Breite umstellt, hat den Sprachschalter nicht erreicht -- seine
Desktop-Regel (.sprach-schalter .nav-dropdown, 0-2-0) ist spezifischer,
und eine @media-Abfrage erhoeht die Spezifitaet nicht. Dadurch lief die
Desktop-Animation "sprach-dropdown-in" weiter, die per fill-mode:both
dauerhaft transform: translateX(-50%) setzt. Auf dem Desktop korrekt
(schmales Fenster mittig unter dem Knopf), im Handy-Menue aber toedlich:
das Fenster ist dort bildschirmbreit und wurde um seine halbe Breite nach
links geschoben (gemessen live: x = -148px bei 390px Viewport).
Fix: dieselben Handy-Regeln erneut mit ausreichender Spezifitaet fuer den
Sprachschalter, samt Kommentar zur Begruendung.
Geprueft mit Playwright (echter Browser): 390x844, 360x640, Querformat
844x390 und Tablet 768x1024 -> Fenster jeweils vollstaendig im Bild, alle
5 Sprachen sichtbar; Desktop 1920 unveraendert schmal und zentriert;
Sprachwechsel (English) funktioniert weiterhin.
Co-Authored-By: Claude Opus 5 <[email protected]>
War beim Server-Deploy schon als Konflikt aufgefallen (Diene/das Team hatte
die richtige Schreibweise bereits korrigiert) -- hier fehlte die Korrektur
noch in i18n-zeitreise.js (alle 5 Sprachen) sowie in der HTML-Fallback-
Version, weil mein ursprünglicher Fix von heute Nachmittag ("Cidem" ->
"Cidgem") selbst schon falsch war.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nutzer-Report mit drei Bildern vom Handy:
1. HERO-BILD SASS NICHT MEHR HINTER DEM TEXT (index.html)
.hero-artwork hat "inset:0" -- füllt also die GESAMTE Höhe von
.hero-cinematic, und diese Sektion umschließt nicht nur die Überschrift,
sondern auch die 3 Welt-Kacheln darunter. Auf dem Handy wird die Sektion
durch den 4-zeilig umbrechenden Titel + Kacheln riesig (~1570px bei
390px Breite) -- das Trio-Bild (16:9, contain-skaliert an die Breite)
wurde dadurch nur ~220px hoch und mittig in dieser riesigen Fläche
zentriert, landete also als schmaler Streifen zwischen den Buttons und
den Welt-Kacheln statt hinter der Überschrift.
Fix: eigenes festes Seitenverhältnis (4:3) für die Bildbox auf dem
Handy, von OBEN verankert statt zentriert, background-size auf "cover"
-- Verlauf eigens für die neue, kürzere Box abgestimmt (die
Desktop-Version wäre zu abrupt gewesen). Über 6 Breiten (320-768px)
mit Playwright gegengeprüft.
2. MENÜ-KNOPF ZU UNAUFFÄLLIG (main.js + main.css, alle Seiten)
"da soll auch menü stehen und die 3 striche" + "die kiste soll auch
leicht eine andere farbe haben so dass sie auffällt, eine leicht blau
tönung". Sichtbares "Menü" neben den drei Strichen ergänzt (neuer i18n-
Schlüssel nav_toggle_label, alle 5 Sprachen) + dezente Babyblau-Tönung
(8% Deckkraft, passend zur Markenfarbe --accent). Dabei einen
unabhängigen, zweiten Bug gefunden und mitbehoben: durch die neue
Knopfbreite/-höhe wurde ein Rechenfehler im geschlossenen Mobilmenü
sichtbar -- "translateY(-110%)" reicht nur, wenn das Panel mindestens
10x so hoch ist wie der Kopfbereich; war das nicht der Fall, ragte die
Unterkante (der Sprachschalter) ein paar Pixel sichtbar ins Bild.
Robusterer Ersatz: -100% + fester 200px-Puffer, unabhängig von Panel-
und Kopfbereichshöhe. Über 3 Breiten gegengeprüft (Panel unsichtbar UND
öffnet weiterhin normal).
3. "ÖFFNEN"-KNOPF AUF DER ZUGANGSSEITE ABGESCHNITTEN (gate.html)
.gate-card trägt "flex: 1 1 220px" für die Desktop-Reihe (220px als
BREITE gedacht). Sobald @media max-width:480px auf flex-direction:column
umschaltet, gilt dieselbe Zahl als HÖHE -- die Karte wurde auf genau
220px Höhe gequetscht. overflow:hidden setzt zusätzlich das normale
Mindestmaß (min-height:auto) auf 0 herunter, wodurch nichts das
Zusammenquetschen verhinderte -- der "Öffnen"-Knopf wurde unten
abgeschnitten. Fix: flex:none in genau diesem Media-Block, Breite bleibt
weiterhin über width:100%/max-width geregelt. An 4 Breiten x 3 Kacheln
(Dogi/VanVan/Diene) gegengeprüft: Karten jetzt 258px statt 220px hoch,
Knopf komplett sichtbar.
Vollständiger Regressionslauf: alle 34 Seiten bei 390px (kein Überlauf,
Menü-Knopf überall erreichbar und beschriftet), Desktop bei 1920px
unverändert (Hamburger weiterhin nur unter der bestehenden 1650px-
Schwelle sichtbar).
Cache-Busting-Version auf 20260821t erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nachtrag auf Nachfrage ("hast du alles geprüft oder nur die menü
leisten?") -- vorher hatte ich nur Navigation, Seitenbreite, Tippflächen
und Hoch/Querformat geprüft. Jetzt zusätzlich Bilder, Texte, Knöpfe und
die kompletten Abläufe.
Geprüft über alle 35 Seiten bei 393px:
- Bilder: kein einziges kaputtes Bild, keine fehlenden alt-Texte
- Dateien: keine 404er
- Knöpfe/Links: alle beschriftet (keine namenlosen Bedienelemente)
- Text: nichts wird abgeschnitten. Die zunächst gemeldeten "Überläufe"
bei .btn/.card waren Fehlalarme -- sie stammen von den dekorativen
Leucht-Ebenen (::before mit negativem inset), echter Text ragt
nirgends heraus (einzeln gegengeprüft).
Zwei echte Funde behoben:
1. Marken-Unterzeile war mit 8,96px zu klein zum Lesen (hatte ich beim
Handy-Fix selbst so verkleinert). Jetzt 11px -- Platz ist da, seit der
Menü-Knopf eigenständig rechts sitzt. Über acht Breiten gegengeprüft,
Kopfleiste bleibt überall stabil.
2. "Aktiv"-Ankreuzfelder in der Verwaltung waren 22px. Jetzt 26px, die
ganze Beschriftungszeile ist 44px hoch und schaltet mit um.
Abläufe am Handy durchgespielt (echte Fingertipps, Fake-Backend):
- Registrierung über alle drei Schritte inkl. falschem Code
- Login mit falschem und richtigem Zugangscode
- Abmelden auf supporter.html
- Stimme einreichen inkl. Profilbild-Auswahl
- Verwaltung: Team-Mitglied anlegen, Stimme freigeben, alle Bereiche
sichtbar, kein Überlauf
Cache-Busting-Version auf 20260821r erhöht.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: "benutz da bitte nur die originalen husky und
hasen. mach nur die zwei. und die auswahl wo die leute selbst ein bild
rein setzen können."
- Auswahl von acht auf zwei reduziert (DogFather-Husky, HasiDog). Die
übrigen Bilddateien bleiben liegen, falls sie je zurücksollen -- es
genügt, die Zeile in data-stimmen-avatare.js und die Id in
ERLAUBTE_AVATARE wieder zu ergänzen.
- Neue Kachel "eigenes Bild" (gestrichelter Rand + Plus), die den
Dateidialog öffnet, das Bild sofort hochlädt und als Vorschau in der
Kachel zeigt.
Bereits freigegebene Stimmen mit einer der entfernten Figuren zeigen
wieder den Anfangsbuchstaben statt eines kaputten Bildes -- die
Auflösung unbekannter Ids liefert null, das war schon so vorgesehen.
Sicherheit des öffentlichen Uploads (bisher war Hochladen bewusst nur
der Verwaltung erlaubt):
- Gleiche multer-Härtung wie der Verwaltungs-Upload: nur JPG/PNG/WebP,
max. 5 MB, zufälliger UUID-Dateiname (kein Originalname).
- Der Server nimmt im Avatar-Feld weiterhin NUR bekannte Ids an oder
eine Adresse, die exakt auf den eigenen Upload-Ordner zeigt und danach
nur aus UUID + Bildendung besteht. Gegengetestet: fremde Domains,
"../"-Ausbruch, .svg/.html, javascript:, angehängte Skripte und http
statt https werden alle abgelehnt.
- Missbrauchsbremse gegen Vollschreiben der Festplatte: max. 10 Uploads
pro Stunde und IP.
- Sichtbar wird ein Bild ohnehin erst, wenn die Stimme freigegeben wird.
Mit Playwright end-to-end geprüft (10 Tests) plus 9 Sicherheitsfälle.
Cache-Busting-Version auf 20260821q erhöht.
Co-Authored-By: Claude Opus 5 <[email protected]>
Wie beim vorherigen Mal lag das nur als Arbeitskopie auf dem Server, nicht
in git. Unverändert übernommen, bevor darauf aufgebaut wird:
- Profilbild-Auswahl für die Stimmen (data-stimmen-avatare.js neu,
stimmen.js, i18n-stimmen.js, stimmen.html, verwaltung.html, main.css)
- Dritte Zugangs-Kachel für Diene (gate.html, server/gate.js)
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Report 21.08.2026 mit Screenshot: "auf dem handy kann ich oben
nicht aussehen in welche seite ich will welche kategorie welche sprache
garnichts". Drei echte, per Playwright reproduzierte Fehler:
1. MENÜ-KNOPF AUSSERHALB DES BILDSCHIRMS (Hauptproblem)
.brand stand auf flex-shrink:0, war bei 390px aber 352px breit. Mit
Abstand + Knopf brauchte die Leiste 423px bei 367px Platz -- der
Menü-Knopf landete bei x=396px, also komplett außerhalb. Damit war auf
dem Handy die GESAMTE Navigation unerreichbar (keine Seiten, keine
Kategorien, kein Sprachwechsel).
Fix: Knopf per margin-left:auto immer an die rechte Kante; Marke darf
unter 620px schrumpfen (inkl. min-width:0, sonst greift flex-shrink
nicht); unter 400px entfällt die reine Deko-Unterzeile.
2. MENÜ IM QUERFORMAT NICHT ZU ÖFFNEN
Das zugeklappte Panel wird um -110% SEINER EIGENEN Höhe verschoben. Quer
(568x320) ist es nur 258px hoch, die Unterkante lag dadurch bei y=36px --
also unsichtbar genau über dem Menü-Knopf (y=11..55) und hat jede
Berührung abgefangen. Fix: pointer-events:none im geschlossenen Zustand.
3. MENÜPUNKTE AUF KURZEN BILDSCHIRMEN ZUSAMMENGEQUETSCHT
.nav-links ist ein Flex-Container fester Höhe; passte der Inhalt nicht,
schrumpfte Flexbox die Einträge (iPhone SE: 59px -> 29px, Knöpfe 21px).
Fix: flex-shrink:0 auf die Kinder, der Bereich scrollt stattdessen
(overflow-y:auto war bereits gesetzt).
Zusätzlich: Fußzeilen- und Impressum/AGB-Links auf Handys als echte
Tippziele (44px statt 17-20px) -- 18 dicht stehende Links, mit dem Finger
vorher kaum zu treffen. Menü-Trennlinien begradigt (folgten dem
Desktop-Pillenradius und sahen aus wie Schüsseln).
Ergebnis: alle 31 Seiten ohne Überlauf, Menü auf 320-768px, hoch UND quer
nutzbar, kleinster Menüpunkt 46px. Verbleibende kleine Ziele sind reine
Fließtext-Links im Satz (dürfen laut Standard klein bleiben).
Desktop per Regressionstest unverändert geprüft.
Cache-Busting-Version auf 20260821p erhöht.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: "bei der ersten registrierung sollen die eine
email bekommen mit einem einmaligen code damit wir auch wissen dass
email stimmt und danach wenn sie den code eingegeben haben sollen die
erst ihren zugangscode auswählen/eintippen können."
Damit wird eine echte Lücke geschlossen: registerSupporter() hat bisher
`email_verified = 1` gesetzt, OHNE dass irgendetwas geprüft wurde -- man
konnte sich mit einer fremden oder erfundenen Adresse registrieren und
kam sofort rein.
Neuer Ablauf in drei Schritten:
1. Name/TikTok/E-Mail -> Konto wird als UNBESTÄTIGT angelegt
(email_verified = 0, noch kein Zugangscode). Es kommt bewusst KEIN
Session-Token zurück -- eingeloggt ist man hier noch nicht.
2. Einmalcode aus der E-Mail eingeben -> verify-email bestätigt und
loggt ein. Die Willkommens-Mail wandert hierher, sie ging vorher an
eine noch ungeprüfte Adresse.
3. Erst jetzt den eigenen Zugangscode festlegen.
Serverseitig abgesichert: setSupporterAccessCode() lehnt ab, solange die
E-Mail nicht bestätigt ist -- der Schritt ist damit nicht nur im
Formular versteckt, sondern auch per Direktaufruf nicht überspringbar.
Wiederverwendet wird die bereits vorhandene Mechanik (issueAuthCode/
verifyAuthCode mit Zweck "verify_email", sendVerifyEmailCode, die Panels
#panel-code und #panel-neuer-code) -- der "Code vergessen?"-Weg nutzt
dieselbe Code-Eingabe und bleibt unverändert; eine neue Variable
codeZweck unterscheidet, welcher Endpunkt aufgerufen wird.
Mit Playwright end-to-end geprüft (14 Tests): Reihenfolge der Aufrufe,
kein Token vor der Bestätigung, falscher Code kommt nicht weiter,
Zugangscode-Feld erst im letzten Schritt, "Code vergessen?" unberührt.
Cache-Busting-Version auf 20260821o erhöht.
Co-Authored-By: Claude Opus 5 <[email protected]>
Diese Änderungen liefen bereits live auf dem Server, lagen dort aber
ausschließlich als nicht eingecheckte Arbeitskopie — bei jedem Deploy
(stash/pull/pop) und bei jedem Serverproblem wären sie verloren gewesen.
Deshalb hier unverändert in git übernommen, bevor darauf aufgebaut wird.
Enthalten (nicht von mir gebaut, nur gesichert):
- Supporter: eigener fester Zugangscode statt Einmalcode-Login
(Migration 0009, lib/crypto.js scrypt-Hash, routes/supporter.js,
abonnieren.html, supporter.html, i18n-abonnieren/-supporter)
- Stimmen: Profilbilder (Migration 0010, routes/testimonials.js)
- Event-Bild-Upload: voller Pfad statt relativem (routes/events.js)
- Neue/überarbeitete Hintergrundbilder für viele Seiten
- Teilen-Funktion (streamplan.js, i18n-index/-streamplan, main.css)
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: "Weg" stand auf manchen Bildschirmbreiten
allein in einer eigenen Zeile, sah unruhig aus. Non-breaking-Space
zwischen den letzten zwei Wörtern in allen 5 Sprachen -- bricht die
Zeile jetzt nie mehr genau zwischen ihnen um.
Cache-Busting-Version auf 20260821m erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: Tippfehler beim Namen des Kooperationspartners
beim Creator Cup korrigiert, in allen 5 Sprachen plus dem
HTML-Fallbacktext.
Cache-Busting-Version auf 20260821l erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: "wenn ich eine änderung mache ist es auch für
jeden für die die schon da sind und die neuen" + "ich will ich titel
und namen von kategorien und seiten ändern können in der verwaltung".
Backend (braucht Filipes manuellen Deploy):
- Migration 0008: team_members bekommt intro/bioHtml/extraCta-Spalten
-- volle Feld-Parität mit den von Hand gepflegten Profilen (Diene/
Patrick/Bananenstift/Marina nutzen diese Felder).
- routes/team.js: neue importLegacyMember()-Funktion -- übernimmt ein
bestehendes Profil 1:1 in die Datenbank, OHNE erneut zu übersetzen
(die vorhandenen, von Hand geschriebenen Übersetzungen bleiben
erhalten). Idempotent: mehrfacher Import erzeugt keine Duplikate.
- routes/site-texts.js (neu): admin-editierbare Kategorie-Namen und
Seitentitel, generischer key->{de,...}-Override über app_settings
(wie "Event des Jahres"), fester Schlüssel-Katalog aus
Sicherheitsgründen. Leeres Feld setzt auf den Standardtext zurück.
- 27 Tests in isolierter Testumgebung geprüft (kein better-sqlite3
lokal kompilierbar).
Frontend:
- window.dogiTeamZusammenfuehren() (main.js): admin-Mitglieder
ÜBERSCHREIBEN jetzt gleichnamige statische Einträge (per slug) statt
sie zu duplizieren -- eine Bearbeitung wirkt dadurch für alle.
- window.dogiSiteTexteLaden() + applyTranslations() erweitert um
data-site-text-key -- Kategorie-Seitentitel (team-modis.html/
team-scouts.html/creator.html/manager.html) sind jetzt live editierbar.
- Verwaltung: "📥 Bestehende Mitglieder importieren"-Knopf (holt VanVan/
Diene/Funny/Miss/Marina/Ghost/Patrick/Bananenstift aus den data-*.js-
Dateien, VanVan bewusst ausgenommen -- eigene Sonderkarte + Seite),
erweitertes Formular (Intro/ausführliche Vorstellung/zweiter Button,
eingeklappt unter "Erweitert"), neue Sektion "Kategorien &
Seitentitel" (4 Karten, sofort wirksam auf Website UND Verwaltung).
Beim Testen einen echten UX-Bug gefunden und gefixt: die "Gespeichert"-
Meldung nach dem Speichern eines Mitglieds wurde von der direkt
anschließenden Formular-Zurücksetzung sofort wieder überschrieben und
war nie sichtbar.
Cache-Busting-Version auf 20260821k erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: "überall wo Modis sind oder Scouts oder
Manager, oder Creator, will ich dass ich die easy über meine
Verwaltungsseite hinzufüge und die automatisch in der Website
hinzugefügt werden ... auch mit Fotos und TikTok Link."
Backend (server-internal, braucht Filipes manuellen Deploy):
- Neue Tabelle team_members (Migration 0007) für alle vier Kategorien
gemeinsam -- ergänzt, überschreibt NIE die von Hand gepflegten
Einträge in data-modis.js/data-scouts.js/data-creator.js.
- routes/team.js: öffentliches Lesen (nur aktive Mitglieder, optional
nach Kategorie gefiltert), TEAM_MANAGE-geschütztes Anlegen/Bearbeiten/
Löschen, Foto-Upload (gleiches Muster wie "Event des Jahres"),
automatische Übersetzung von Rolle/Bio/Zitat wie bei anderen
admin-gepflegten Texten. Slug global eindeutig (mit automatischer
Kollisionsauflösung), TikTok-Kurzname wird zu voller URL ergänzt.
27 Tests in isolierter Testumgebung geprüft (kein better-sqlite3
lokal kompilierbar).
Frontend:
- window.dogiTeamLaden() in main.js: holt admin-gepflegte Mitglieder
einer (oder aller) Kategorien und bringt sie in exakt dieselbe Form
wie die bestehenden data-*.js-Einträge.
- team-scouts.html/team-modis.html/creator.html hängen das Ergebnis
einfach an ihre bestehenden Arrays an und rendern erneut -- exakt
derselbe Look wie die schon bestehenden Profile (Foto/Avatar-Initiale,
Rolle, Zitat, TikTok-Button). creator.html hatte bisher ein "return"
bei leerem CREATORS-Array, wodurch admin-Creator NIE geladen worden
wären -- gefixt. team-modis.html berücksichtigt Rang/Rang-Bezeichnung
für die Pyramide.
- Neue Sektion "Weitere Manager" auf manager.html, komplett unsichtbar
bis der erste Manager angelegt wird (data-manager.js neu, wie
data-creator.js aktuell leer).
- profil.html sucht jetzt kategorieübergreifend auch in admin-gepflegten
Profilen, inkl. korrektem Theme/Zurück-Link auch für Manager.
Verwaltung: neue Sektion "Team verwalten" (TEAM_MANAGE-Berechtigung) --
ein Formular für alle vier Kategorien mit Foto-Sofort-Upload,
TikTok-Feld, Bio/Zitat, bedingten Rang-Feldern (nur Modi), Kategorie-
Filterleiste und Bearbeiten/Löschen pro Eintrag.
Beim Testen mit Playwright einen echten Syntaxfehler gefunden und
gefixt (ASCII-Anführungszeichen statt schließendem „" in einem
Statustext), der das GESAMTE Verwaltungs-Skript und damit die komplette
Seite lahmgelegt hätte.
Cache-Busting-Version auf 20260821j erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Beide heutigen Meldungen ("pr_quote_open...", "ts_profil_ansehen") waren
KEIN Caching-Problem, sondern ein echter Bug in main.js: nach Klick auf
einen internen Link und dann "Zurück" (oder generell jede zweite Seite
innerhalb einer Browser-Sitzung) wurde die seiteneigene i18n-*.js-Datei
nie erneut ausgeführt -> window.I18N_PAGE blieb auf null -> jede
Übersetzung fiel auf den rohen Schlüsselnamen zurück.
Ursache: skripteUebernehmen() erkennt i18n-Dateien am Muster ".js$"
(String-Ende). Seit die Cache-Busting-Version ("?v=...") an jede
Skript-URL angehängt wird, endet der echte src-Wert aber nie mehr auf
".js", sondern auf ".js?v=...". Der Test schlug seitdem für JEDE
i18n-Datei fehl und sie wurde wie eine normale, schon geladene Datei
behandelt und beim nächsten Seitenwechsel übersprungen.
Mit Playwright reproduziert (Klick auf Profil-Kachel + Zurück-Button)
und nach dem Fix erneut verifiziert -- betraf praktisch jede Seite mit
eigenem i18n-*.js beim Navigieren per Klick, nicht nur team-scouts.html.
Cache-Busting-Version auf 20260821i erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: Überschrift + Button "Alle Aktionen & Projekte"
auf index.html weg. data-aktionen.js-Script-Tag (nur noch dafür gebraucht)
und die zugehörigen JS-Renderzeilen ebenfalls entfernt, dazugehörige
i18n-Keys (idx_aktionen_h2/idx_aktionen_btn) aus i18n-index.js aufgeräumt.
aktion-detail.html und data-aktionen.js selbst bleiben unangetastet.
Cache-Busting-Version auf 20260821h erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: Patricks Bio endete nur mit "- euer Patrick",
Bananenstift hat zusätzlich eine zweite Zeile "Scout von Dogfather".
Für Konsistenz zwischen beiden Scout-Profilen in allen 5 Sprachen ergänzt.
Cache-Busting-Version auf 20260821g erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: unter dem Namen/Rolle-Text je ein TikTok-Button
(@patrick180585 bzw. @bananenstift009). Beide nutzen den bereits
bestehenden social-Mechanismus in profil.html (social.tiktok -> echter
.btn-tiktok-Button), kein neuer Code nötig.
Cache-Busting-Version auf 20260821f erhöht (data-scouts.js ist .js und
damit von Cloudflares erzwungenem Edge-Cache betroffen).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: erstes Fan-Treffen von Dogi & Tili (Team
TiliDog) in Wuppertal ergänzt -- gleichzeitig das erste persönliche
Aufeinandertreffen von DogFather und Tili. Als Meilenstein markiert und
chronologisch korrekt zwischen "Juli 2026 — Start als Manager" und
"27. Juli bis 2. August 2026 — Creator Cup" einsortiert.
Cache-Busting-Version auf 20260821e erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: "füge das foto was ich am ende mitschicke
neben den text im screen1". Sektion von einspaltigem Fließtext auf
grid-2 umgebaut, Foto (assets/img/streamer-filipe-portrait.jpg, aus
Pictures/Filipe, auf 1000x1500 verkleinert) rechts daneben mit
frame-gold-Rahmen für Abwechslung zur Casper-Sektion (frame-lila).
Cache-Busting-Version auf 20260821d erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Der Button gehört thematisch besser zum Modi-Team als zur Casper-Sektion
auf streamer.html (Nutzer-Wunsch 21.08.2026: "den knopf da weg bitte und
in die modie seite zu den modis hinzufügen und perfekt in die seite
anpassen"). Jetzt im Hero von team-modis.html, unter dem Lead-Text,
zentriert im bestehenden btn-row-Muster der Seite.
Cache-Busting-Version auf 20260821c erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Vorheriger max-height-Deckel (460px) fürs sehr hochkantige
streamer-mascot.jpg (900x2812) war zu knapp und ließ eine sichtbare
Lücke neben dem längeren Text ("die größe vom bild vom husky soll dem
text rechts nebendran angepasst werden"). Deckel auf 720px erhöht
(orientiert an der typischen Texthöhe in diesem Abschnitt), Grid-Stretch-
Ansatz ausprobiert und wegen Rückkopplung mit dem extremen
Seitenverhältnis verworfen (siehe Kommentare in main.css/streamer.html).
Cache-Busting-Version auf 20260821b erhöht (Cloudflare cached CSS/JS
sonst bis zu 4h am Edge).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nutzer-Wuensche 20.08.2026 (2. Runde):
- Kategorie "DogFather" -> "Filipe", Kategorie "HasiDog" -> "Dogi&Hasi".
- Unterpunkt "Streamer" (streamer.html) aus "Filipe" heraus nach
"Dogi&Hasi" verschoben, dort GANZ NACH OBEN (ueber "HasiDog") und in
"DogFather" umbenannt.
- Unterpunkt "HasiDog-Welt" -> "HasiDog".
- Fusszeile zieht mit: Spaltenueberschrift nutzt jetzt dieselbe
Kategorie-Bezeichnung wie die Nav ("Filipe" / "Dogi&Hasi & Manager"),
streamer.html steht dort ebenfalls in der Dogi&Hasi-Spalte ganz oben.
Die internen Schluesselnamen (nav_dogfather...) bleiben bewusst
unveraendert -- reine Bezeichner, ein Umbenennen waere nur Fehlerquelle.
- "die kachel soll noch spezieller und geiler aussehen": Einreich-Kachel
auf stimmen.html deutlich aufgewertet -- wandernder Farbverlauf-Rahmen
(Zwei-Ebenen-/background-position-Technik, KEIN rotierender Ring: siehe
dokumentierte Projekt-Lektion zu Verzerrungen auf eckigen Flaechen),
schwebende Herz-Partikel, Medaillon statt nacktem Emoji,
Farbverlauf-Ueberschrift, aufleuchtende Eingabefelder.
- "und auch die die danach kommen ... sollen viel geiler sein": freigegebene
Stimmen sind jetzt echte Praesentationskarten -- farbige Akzentlinie oben,
grosses Anfuehrungszeichen als Wasserzeichen, Avatar-Medaillon mit
Anfangsbuchstabe, TikTok-Handle als eigener Chip, sanftes Anheben beim
Ueberfahren.
Alles augenschonend gehalten (gedeckte Toene, langsame Bewegungen,
vollstaendiger Stillstand bei prefers-reduced-motion) und per Playwright
visuell geprueft, keine JS-Fehler.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wuensche 20.08.2026:
- hasidog.html: TikTok-Knopf direkt unter der grossen Ueberschrift,
Account @hasidog0804 (alle 5 Sprachen uebersetzt).
- streamer.html: TikTok-Knopf unter "Casper - mein treuer Begleiter",
Account @dogis.modi.gang (alle 5 Sprachen uebersetzt).
- zeitreise.html: die beiden letzten Karten getauscht -- der Website-Start
(21.08.2026, konkretes Datum) steht jetzt VOR der Teddy-Kooperation
("Datum folgt"), damit die Zeitleiste durchgehend chronologisch bleibt.
- streamer.html Bildgroesse gefixt ("der soll bissl kleiner sein und nicht
so riesig"): streamer-mascot.jpg ist 900x2812 px und lief mit
aspect-ratio:auto + height:auto in voller natuerlicher Hoehe -- rund
dreimal so hoch wie die Textspalte daneben. Neue Klasse
.collage-photo-kompakt deckelt die Hoehe auf 460px und laesst den Rahmen
eng am Bild sitzen (width:fit-content), die ganze Figur bleibt sichtbar.
Regel steht bewusst NACH ".collage-photo img" -- gleiche Spezifitaet,
die spaetere gewinnt, sonst haette width:100%/height:100% sie aufgehoben.
Alles per Playwright verifiziert (beide Knoepfe mit korrekten Links,
Bildhoehe 460px statt ~1780px, neue Zeitreise-Reihenfolge), keine JS-Fehler.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 20.08.2026: "eine richtig geile kachel ... wo die leute mit
namen und tiktok namen mir eine nachricht schreiben können die ich in die
verwaltung kriege, und dann kann ich die ausgewählten über die
verwaltungsseite auf die website hinzufügen ... das wird mega persoenlich
zu den fans, bitte wirklich krass geil speziell."
- Neue, augenschonend gestaltete Einreich-Kachel auf stimmen.html: Name,
TikTok-Name (optional), Nachricht -- landet NIE automatisch oeffentlich,
sondern immer erst als Entwurf in der Verwaltung.
Warmer Babyblau/Rosé-Farbverlauf, wandernder Lichtschein, pulsierendes
Herz -- ersetzt die 3 ewigen "Hier steht bald..."-Platzhalterkarten.
- Neue Verwaltungs-Sektion "💬 Stimmen verwalten": Warteschlange (offene
zuerst), Freigeben/Ablehnen/Löschen pro Eintrag.
- Freigegebene Stimmen erscheinen automatisch in einer neuen, spezielleren
Zitat-Kartenoptik (großes Anführungszeichen, Name + TikTok-Chip) --
Abschnitt bleibt komplett unsichtbar, solange keine einzige freigegeben
wurde.
- Backend: neue Tabelle `testimonials` (Migration 0006), routes/
testimonials.js (oeffentliches Einreichen + Lesen freigegebener,
admin-Warteschlange + Status/Loeschen mit neuer TESTIMONIALS_MANAGE-
Berechtigung). 18 automatisierte Tests gegen eine Fake-DB bestanden.
- Alles per Playwright visuell durchgespielt: leerer Zustand, Einreichen
-> Erfolgsmeldung, freigegebene Stimmen-Anzeige, Verwaltungs-Warteschlange
mit allen Aktionen.
Backend-Teil (server-internal/, cloudflare-worker/migrations/) noch ohne
Deploy-Zugriff -- Dogi muss ihn manuell auf dogiintern ausrollen.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 20.08.2026: "wuensch mir nur noch bissl farbe und sehr
wichtig ist dass ich auch spezielle live events da auch eintragen kann
in der verwaltungsseite so dass da eine zweite uhr erscheint wo die zeit
dann fuer dieses spezielle event laeuft."
- Neue Verwaltungs-Sektion "Spezielles Live-Event": Titel (Deutsch, wird
automatisch uebersetzt), echtes Datum+Uhrzeit, optionaler Link, Aktiv-
Schalter -- nur mit Titel + Zukunftsdatum aktivierbar.
- Zweite Uhr auf streamplan.html (Magenta/Violett statt Cyan/Gold, direkt
neben der bestehenden), nur sichtbar wenn ein Event aktiviert ist und
das Zieldatum noch nicht vorbei ist. Echter Countdown inkl. Tage (z.B.
"2T 03:14:59"), "Jetzt"-Zeiger zeigt wie bei Uhr 1 die tatsaechliche
Uhrzeit, der magentafarbene Fixpunkt markiert die Tageszeit des Events.
Zieldatum wird als UTC gespeichert -- jede besuchende Person sieht den
exakt richtigen Countdown in ihrer eigenen Zeitzone.
- "Bissl Farbe": bunter Farbverlauf (Cyan/Violett/Gold) auf dem aeusseren
Ring statt reinem Grauton, kraeftigerer Sweep-Farbschein.
- Backend: neue routes/special-event.js (getSpecialEventPublic nur bei
aktiv+zukuenftig, getSpecialEventAdmin fuer Entwuerfe, saveSpecialEvent
mit Validierung), 13 automatisierte Tests gegen eine Fake-DB bestanden.
- Bugfix unterwegs gefunden (Playwright-Screenshot, wiederholtes Muster
auf dieser Seite): .stream-radar-wrap blieb trotz [hidden]-Attribut
sichtbar (display:block ueberschreibt die eingebaute [hidden]-Regel bei
gleicher Spezifitaet) -- explizite Regel ergaenzt, per Playwright erneut
verifiziert (display:none bestaetigt).
Backend-Teil (server-internal/) noch ohne Deploy-Zugriff -- Dogi muss ihn
manuell auf dogiintern ausrollen, sonst bleibt die zweite Uhr unsichtbar.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Report per Screenshot-Vergleich: "Medien"-Kategorie ist mittig
unter dem Knopf, der Sprachschalter (DE/CH/EN/FR/PT) aber rechtsbuendig --
war bewusst so gebaut, als der Schalter noch ganz am rechten Rand sass.
Seit DogiCrew-/Bewerben-Knopf daneben stehen, ist genug Platz fuer
dieselbe zentrierte Ausrichtung wie ueberall sonst -- macht die Optik
konsistent und behebt nebenbei einen Detail-Fehler: der Verbindungspfeil
zeigte schon immer mittig, waehrend die Box selbst rechts daneben sass.
Per Playwright verifiziert: Dropdown jetzt exakt unter dem Knopf zentriert,
laeuft bei keiner getesteten Breite ueber den Rand.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 20.08.2026: Startseiten-Hero (universe-trio.jpg) und
Streamplan-Hero (bg-streamplan.jpg/-mobile.jpg) durch neu bereitgestellte
Bilder ersetzt. Blur-Variante fuer die Startseite neu aus dem frischen
Bild erzeugt (Gaussian Blur, passend zur bestehenden Cover-Verlauf-Technik).
Mobile-Ausschnitt fuer Streamplan mehrfach nachjustiert, damit der
"STREAMPLAN"-Schriftzug im schmalen Hochformat-Crop komplett sichtbar
bleibt. Alte Bilder als .bak-20-08-2026 gesichert (nicht eingecheckt).
Referenzen mit Versions-Stempel (?v=) versehen, damit der neue Stand
sofort sichtbar ist statt bis zu 4 Std im Cache zu haengen.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Report per Screenshot: Klick auf eine Kategorie (z.B. "DogFather")
liess das Untermenue offen stehen, bis irgendwo anders hingeklickt wurde --
verliess man es einfach mit der Maus, blieb es haengen. Jetzt schliesst
sich ein per Klick geoeffnetes Menue automatisch, sobald die Maus die
Kategorie (Knopf + Untermenue) verlaesst -- nur auf echten Maus-Geraeten
(hover:hover + pointer:fine), auf Touch/Tablet aendert sich nichts, dort
gibt es kein "mit der Maus verlassen". Per Playwright verifiziert: Klick
oeffnet, Mausbewegung weg schliesst.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 20.08.2026: "diese seite vom streamplan soll viel geiler
und spezieller sein, ueberrasch mich."
Neues Herzstueck: ein 24-Stunden-Ziffernblatt (reines SVG, keine
Bild-Assets), das den festen 20-Uhr-Termin als dauerhaft leuchtenden
Fixpunkt zeigt (goldener Puls) und einen "Jetzt"-Zeiger in Echtzeit mit
der tatsaechlichen Uhrzeit der besuchenden Person mitbewegt (Babyblau,
DogFather-Markenfarbe). Nutzt denselben /live-status-Endpunkt wie die
Startseite:
- Offline: echter Sekunden-Countdown zum naechsten lokalen 20-Uhr-Termin.
- Live: komplettes Radar schaltet auf Rot/Puls um, zeigt den Stream-Titel
und einen "Jetzt anschauen"-Knopf direkt zu TikTok.
Sanft rotierender Lichtschein fuer Atmosphaere, komplett augenschonend
(gedeckte Farben, respektiert prefers-reduced-motion vollstaendig).
Bugfix unterwegs gefunden (Playwright-Screenshot, dritte Wiederholung
desselben Musters heute): der "Jetzt anschauen"-Knopf blieb trotz
[hidden]-Attribut sichtbar, weil .btn selbst "display" setzt und damit
gleiche Spezifitaet wie die eingebaute [hidden]-Regel hat -- explizite
Regel ergaenzt.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 20.08.2026: "diese zwei kisten sollen leer sein solang wie
ich nichts rein setze, am besten sollen die sogar immer nur erscheinen
wenn ich was rein setze und sie aktiviere ... wen ich drauf druecke dass
dann ein kleines fenster aufgeht wo das bild bissl groesser ist mit einem
groesseren text und beschreibung, und mit einem link ... die kacheln
sollen auch bissl spezieller sein."
- Kein hartkodierter Standardinhalt mehr auf der Startseite -- die Kachel
UND der ganze Abschnitt bleiben komplett unsichtbar, bis mindestens ein
Event in der Verwaltung ausgefuellt UND ueber einen neuen "Aktiv"-Schalter
freigeschaltet ist. Genau 1 aktives Event -> zentrierte Einzelkachel
statt halbleerem Zwei-Spalten-Raster.
- Klick auf eine Kachel oeffnet jetzt ein Detail-Fenster (groesseres Bild,
groesserer Titel/Text, optionaler direkter Link) statt sofort
wegzunavigieren.
- Kacheln bekommen einen goldenen Trophaeen-Akzent + dezenten wandernden
Lichtschimmer statt der neutralen Standardkarten-Optik.
- Bugfix unterwegs gefunden (Playwright-Screenshot): .jahres-event-card
blieb trotz [hidden]-Attribut sichtbar (dieselbe Ursache wie der
frühere .jahres-event-bild-Bug: display:block ueberschreibt die
eingebaute [hidden]-Regel bei gleicher Spezifitaet) -- explizite
[hidden]-Regel ergaenzt.
- Backend: server-internal/routes/events.js liefert oeffentlich NUR noch
aktivierte Slots aus (getEventsPublic), neuer authentifizierter Endpunkt
getEventsAdmin liefert der Verwaltung auch Entwuerfe zum Vorausfuellen.
10 automatisierte Tests gegen eine Fake-DB bestanden.
Backend-Teil (server-internal/) noch ohne Deploy-Zugriff -- Dogi muss ihn
manuell auf dogiintern ausrollen, sonst bleibt die Startseite beim alten
Verhalten (immer beide Slots zeigen, kein Aktiv-Schalter in der Verwaltung).
Co-Authored-By: Claude Opus 5 <[email protected]>
Die Erhoehung auf 1900px eben war ein Fehlgriff -- der Nutzer sah dadurch
bei seiner eigentlichen Fensterbreite (die volle Desktop-Nav laengst
gepasst haette, zweifach live bestaetigt) nur noch die schmale Menue-
Ansicht statt der gewohnten vollen Leiste. 1650px war die korrekte,
bereits bestaetigte Schwelle -- das eigentliche Problem war durchgehend
Browser-/CDN-Caching, nicht die Schwelle selbst.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer meldet weiterhin Ueberlauf trotz zweifach bestaetigtem Live-Test
(exakt seine Fensterbreite 1993x931 gegen den echten Server, 0 Ueberlauf,
mehrfach reproduziert) -- Ursache vermutlich hartnaeckiger lokaler Cache
im jeweiligen Browserprofil, nicht mehr abschliessend ferndiagnostizierbar.
Statt weiter zu diskutieren: Sicherheitsabstand brachial vergroessert,
unabhaengig von der genauen Ursache. Hamburger-Schwelle 1650px -> 1900px --
deckt praktisch jede Laptop-/Desktop-Fensterbreite ab, echte Desktop-Nav
zeigt sich jetzt erst ab sehr breiten Fenstern (>1900px), dort mit viel
Luft (min(1560px, 94vw)).
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Report: "ich kann sie immer noch nicht runter laden" -- Manifest +
Service Worker reichen technisch fuer Installierbarkeit, aber ohne
sichtbaren Knopf muss man wissen, dass Chrome/Edge das Adressleisten-
Symbol/3-Punkte-Meny dafuer versteckt. Jetzt: echter Knopf im Footer
("Als App installieren", jede Seite) und in der Verwaltung-Session-Leiste
("Als eigene App installieren"), nutzt beforeinstallprompt + prompt() --
loest pro Seite automatisch mit GENAU dem Manifest aus, das diese Seite
selbst verlinkt (index.html -> manifest.json, verwaltung.html ->
manifest-verwaltung.json), kein Sonderfall-Code noetig. Bleibt unsichtbar,
wenn der Browser das nicht unterstuetzt (Safari/iOS) oder die Seite schon
als App laeuft.
Ausserdem: eigener apple-mobile-web-app-title fuer verwaltung.html
("DogiCrew-Verwaltung" statt generisch "DogFather" beim iOS-Home-Bildschirm).
Cache-Busting-Version (?v=) erneut hochgezaehlt (20260820 -> 20260820b),
da main.js sich durch diese Aenderung erneut geaendert hat.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 20.08.2026: "ich will die Verwaltungsseite auch herunter
laden koennen, so dass ich die originale website und die verwaltungsseite
2 mal getrennt installieren kann, auf dem pc und handy."
- Eigenes manifest-verwaltung.json (eigene "id"/"scope" nur fuer
verwaltung.html, eigener Name "DogiCrew-Verwaltung", eigenes
Icon-Set) statt des site-weiten manifest.json (scope "/") -- macht sie
zu einer technisch eigenstaendigen App-Identitaet, installierbar
parallel zur Haupt-Website, auf Desktop und Handy.
- Neue Icons: bestehendes Husky-Logo mit Violett/Gold-Verlauf statt
Babyblau (passend zum "Jewelen-Tresor"-Look der Verwaltungsseite),
damit beide installierten Apps auch optisch klar unterscheidbar sind.
- Kein zweiter Service Worker noetig -- /sw.js laeuft bereits site-weit
auf Scope "/" und deckt verwaltung.html automatisch mit ab.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Report per Screenshot: "DogiCrew"-Knopf/"BALD"-Badge rechts
abgeschnitten. Ursache: die Hamburger-Schwelle (1480px) und der
Nav-Bar-Breiten-Deckel (1440px) wurden schon zweimal knapp nachgezogen,
reichten aber nicht mehr, seit die Nav um den "DogiCrew"-Knopf + "BALD"-
Badge gewachsen ist (braucht jetzt real ~1491px). Ergebnis: bei JEDER
Fensterbreite ab ca. 1500px (nicht nur in einer schmalen Uebergangszone)
lief die Nav dauerhaft ~50px ueber den Rand.
Diesmal mit echtem Sicherheitsabstand statt wieder nur knapp behoben:
Schwelle 1480px -> 1650px, Deckel 1440px -> 1560px. Per Playwright ueber
den kompletten Bereich 1024-2560px nachgeprueft, keine Ueberlaeufe mehr.
Header ist site-weit eine gemeinsame Vorlage (main.js/main.css), Fix gilt
damit automatisch fuer alle Seiten.
Co-Authored-By: Claude Opus 5 <[email protected]>
Naechste "Ausbaustufe" aus Dogfather_VanVan_Supporter_Abo.odt Abschnitt 20
(siehe Supporter-Abo-System.md), auf Nutzerwunsch "perfektioniere meine
Verwaltungsseite": Dogi/VanVan koennen in verwaltung.html eine Frage mit
2-6 Antwortoptionen auf Deutsch erstellen, automatische Uebersetzung beim
Speichern (gleiches Muster wie "Event des Jahres"). Jede aktive DogiCrew-
Person sieht die Abstimmung in ihrem Supporter-Bereich, stimmt genau einmal
ab (UNIQUE-Constraint in der DB, nicht nur Anwendungslogik), sieht danach
die Live-Ergebnisse. Admin-Seite zeigt Ergebnisbalken live, kann schliessen/
wiedereroeffnen/loeschen.
- Neue Migration 0005_supporter_polls.sql (supporter_polls,
supporter_poll_votes), neue Berechtigung POLLS_MANAGE.
- server-internal/routes/polls.js: 30 End-to-End-Tests gegen eine
Fake-DB bestanden (better-sqlite3 laesst sich lokal nicht kompilieren).
- verwaltung.html: neue "Abstimmungen"-Kiste im bestehenden
vw-overview-box-Stil (violett/pink Ergebnisbalken).
- supporter.html: neue "Aktuelle Abstimmung"-Karte im bestehenden
Gold-Look, Optionen -> Stimme -> Ergebnisbalken, alle 5 Sprachen.
Backend-Teil (server-internal/, cloudflare-worker/migrations/) noch ohne
Deploy-Zugriff -- Dogi muss ihn manuell auf dogiintern ausrollen.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 20.08.2026, vor morgigem oeffentlichem Start: "die leute
sollen das ja nicht selbst auswaehlen koennen". Der Schalter erkannte
Dogi/VanVan bisher nur ueber das rein client-seitig lesbare dogi_role-
Cookie (bewusst NICHT das echte HttpOnly-Sicherheits-Cookie) -- technisch
liesse sich dieses Cookie per Browser-Konsole selbst setzen. Echte Daten
waeren dadurch nie einsehbar (nur eigene Beispieldaten-Vorschau), aber
"soll weg fuer die Oeffentlichkeit" heisst hier bewusst ganz weg, nicht
nur sicherer.
Nur der Aufruf beim Seitenaufbau ist auskommentiert, renderVorschauSchalter()
selbst bleibt unangetastet fuer ein spaeteres internes Testen.
Per Playwright verifiziert: Widget erscheint weder bei normalem Besuch
noch mit manuell gesetztem dogi_role-Cookie.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 20.08.2026: "will ich in der admin seite das selbst
gestalten können, mit bild und text und am besten auch einen link." Auf
Rueckfrage entschieden: Titel/Text nur auf Deutsch eingeben, die anderen
4 Sprachen werden beim Speichern automatisch uebersetzt (MyMemory, 0€,
kein API-Key) -- bewusste Ausnahme von der sonst geltenden "immer echte
Uebersetzung"-Regel, klar dokumentiert und im Admin-UI selbst als Hinweis
sichtbar. de-CH bekommt denselben deutschen Text (Dialekt ist keine von
Uebersetzungs-APIs unterstuetzte Zielsprache).
Backend (server-internal):
- routes/events.js: getEventsPublic (oeffentlich, keine Session),
saveEvent + uploadEventImage (beide hinter neuer EVENTS_MANAGE-
Berechtigung, Owner immer erlaubt). Speichert in der bereits
bestehenden app_settings-Tabelle (2 feste Slots) statt einer neuen
Tabelle -- es gibt nie mehr als genau 2 Events.
- lib/translate.js: MyMemory-Anbindung mit "fail closed auf Deutsch"
pro Sprache, falls der Dienst mal nicht antwortet.
- Bild-Upload per multer, zufaelliger Dateiname (crypto.randomUUID,
verhindert Path-Traversal ueber den Originalnamen komplett), 5 MB
Limit, nur jpeg/png/webp, Ablage unter /var/lib/dogfather-internal/
uploads/events (NICHT im Git-Ordner -- uebersteht Deploys), oeffentlich
ausgeliefert unter /uploads.
- Neue Berechtigung EVENTS_MANAGE im Katalog (Gruppe "Startseite").
Frontend:
- index.html: laedt /events-of-year beim Aufruf, ueberschreibt pro Slot
Datum/Titel/Text/Bild/Link NUR wenn dort tatsaechlich etwas gespeichert
ist -- bleibt der Abruf aus oder ist ein Slot leer, bleibt der bisherige
fest eingebaute Standardinhalt (dieselben zwei echten Events) stehen.
Kein Blocker, kein sichtbarer Fehler bei Ausfall.
- verwaltung.html: neue Sektion "🏆 Event des Jahres" (nur mit
EVENTS_MANAGE sichtbar), 2 Karten mit Bild-Upload+Vorschau, Datum,
Titel, Text, Link, eigenem Speichern-Knopf pro Event.
Ausfuehrlich getestet, weil server-internal wegen fehlender Visual-
Studio-Build-Tools auf dieser Windows-Maschine nicht lokal mit echtem
better-sqlite3 laufen kann: routes/events.js komplett isoliert gegen eine
Fake-DB getestet (11 Szenarien: oeffentlicher Abruf, fehlende Session,
Session ohne Recht, Owner, Rolle MIT EVENTS_MANAGE, alle Validierungen,
Bild-Upload inkl. falscher Dateityp, Abruf des hochgeladenen Bilds).
index.html per Playwright mit echtem Netzwerk-Mocking gegen zwei
Szenarien getestet (API nicht erreichbar -> Standardinhalt bleibt; API
liefert echte Daten -> nur der befuellte Slot wird ueberschrieben, der
leere bleibt Standard). Dabei einen echten CSS-Bug gefunden und behoben
(display:block auf .jahres-event-bild überschrieb die [hidden]-Regel des
Browsers, leeres Bild waere immer sichtbar gewesen). verwaltung.html per
Playwright mit gemocktem Login+API end-to-end getestet: Formular wird
korrekt vorbefuellt, Bild-Upload + Speichern senden die richtigen Daten.
WICHTIG: server-internal laeuft unter einem eigenen Systembenutzer
(dogiintern), auf den ich (claudian) bewusst KEINEN Zugriff habe -- diese
Aenderung kann ich anders als sonst nicht selbst bis auf den Server
bringen. Dogi muss den Deploy-Schritt fuer server-internal selbst
ausfuehren (git pull + npm install + Neustart des dogiintern-Dienstes).
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 20.08.2026: "Wege entstehen dadurch, dass man sie geht."
(alle 5 Sprachen). Ersetzt "Zitat folgt" auf der Scout-Karte.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 20.08.2026: bg-bewerben-creator.jpg + -mobile.jpg (bisher
unscharfes Selfie mit pinker Sonnenbrille) ersetzt durch das vom Nutzer
gelieferte Motiv (Spicy-Media-Look, rot, Silhouette + Logo). Alte Version
lokal gesichert (*.jpg.bak-20-08-2026, nicht eingecheckt).
Co-Authored-By: Claude Opus 5 <[email protected]>