KI-Roboterfuchs am Laptop auf Bahngleisen – Sinnbild für Schreiben und Dokumentieren

Blog

Hier schreibe ich über meinen Weg – Gelerntes, Gebautes, Gedanken.
Offen, ehrlich, mutig.

Alle Beiträge

9. September 2026 Projekt

Ein Dashboard, das mitdenkt: neue Mitglieder auf einen Blick

Bisher musste ich in jede meiner Apps einzeln hineinschauen, um zu sehen, ob sich jemand Neues angemeldet hat. Heute habe ich dem ein Ende gesetzt: ein zentrales Admin-Dashboard, das LernyTube, Whisky-Kuratorium und EIS Schuh-Atelier automatisch im Hintergrund abfragt und mir übersichtlich anzeigt, wer sich wann mit welcher E-Mail-Adresse angemeldet hat – inklusive dem Speicherplatz, den jemand mit eigenen Fotos belegt. Ein Klick auf einen der App-Buttons sortiert die Liste sofort auf die jeweilige Anwendung. Ein Hintergrund-Agent prüft alle zwei Minuten von selbst nach, ganz ohne dass ich manuell nachschauen muss.

Nebenbei ist mir aufgefallen, dass mein Schuh-Atelier bei der Registrierung bisher gar keine E-Mail-Adresse abgefragt hat – das habe ich gleich mit ergänzt. Und weil mir wichtig war, dass ich als Betreiberin trotzdem nicht in die privaten Fotosammlungen meiner Nutzer:innen hineinschauen kann, überträgt das Dashboard bei EIS bewusst nur die Summe der Dateigrößen, nie die Bilder selbst. Jede:r hat ihren eigenen Schuh-Schrank.

Die größte Geduldsprobe kam beim Einrichten der neuen Domains dashboard.eiskopani.de und bewerbungsmappe.eiskopani.de: kaum war der DNS-Eintrag gesetzt, hat mein Server-Zertifikat-Dienst mich mit einem Rate-Limit ausgebremst, weil er es kurz zuvor schon zu oft ohne gültige DNS-Antwort versucht hatte. Dazu kam noch, dass mein eigener Server eine "nicht gefunden"-Antwort eine Weile zwischengespeichert hatte, obwohl die Adresse längst korrekt eingetragen war. Am Ende half nur eins: abwarten, bis die Zwischenspeicherung von selbst ablief, und den Reverse-Proxy einmal neu anstoßen. Beide Seiten laufen jetzt sauber über HTTPS.

9. September 2026 KI & Automatisierung

Das Lernbuch: mein eigener KI-Lehrer sortiert sich selbst

In LernyTube ist heute eine neue Funktion entstanden, die mir richtig Freude macht: das "Lernbuch". Ich kann dort eine Frage stellen, Claude antwortet wie ein Lehrer – und sortiert Frage und Antwort danach von selbst in einen Themenbaum ein, ganz ohne dass ich etwas anlegen oder aufräumen muss. Im Test habe ich zwei verwandte Python-Fragen gestellt, die korrekt im gleichen Thema landeten, und eine Geschichtsfrage, die sich automatisch ein eigenes neues Thema geschaffen hat. Vorerst ist die Funktion nur für meinen eigenen Account freigeschaltet.

Danach habe ich gezielt Tests dafür geschrieben, unter anderem zwei Sicherheitstests: einen, der prüft, dass wirklich niemand außer mir an die Funktion herankommt, und einen sogenannten IDOR-Test. IDOR steht für "Insecure Direct Object Reference" – im Klartext: Was passiert, wenn jemand einfach die ID eines fremden Lernbuch-Eintrags in der Adresse ausprobiert? Der Test stellt sicher, dass genau das ins Leere läuft.

Beim Versuch, alles zu pushen, kam eine unangenehme Überraschung zutage: Die GitHub-Actions-Pipeline lief seit einer Branch-Umbenennung gar nicht mehr automatisch, weil der Trigger noch auf den alten Namen "main" zeigte, während ich längst auf "clean-main" arbeite. Das habe ich korrigiert – der automatische Deploy bleibt bewusst weiter deaktiviert, nur die Tests sollen wieder laufen. Und kaum lief die Pipeline wieder, förderte sie gleich einen zweiten, älteren Bug zutage: Meine eigene 404-Fehlerseite griff auf einen Ordner zu, der nur auf meinem eigenen Server existiert, und stürzte deshalb in jeder anderen Umgebung bei jedem "Seite nicht gefunden"-Fehler ab. Auch das ist jetzt robust gemacht. Am Ende lief die komplette Testsuite grün auf GitHub, alles committed und gepusht.

9. September 2026 Projekt

Meine Bewerbungsmappe: ein KI-Kollege für die Jobsuche

Heute ist ein komplett neues Projekt entstanden: die "Bewerbungsmappe" unter bewerbungsmappe.eiskopani.de. Die Idee ist simpel und kam aus meinem eigenen Alltag – für jede interessante Stellenanzeige lege ich eine eigene digitale Mappe an, mit Stellentitel, Firma, Link zur Anzeige und einem Status von "Interessant" bis "Zusage". Das Herzstück ist ein Chat mit einem KI-Job-Agenten direkt in jeder Mappe, der meine Stellenanzeige und meinen Lebenslauf kennt und mir gezielt bei der Vorbereitung auf Vorstellungsgespräche hilft.

Technisch steckt dahinter FastAPI mit einer eigenen PostgreSQL-Datenbank, alles in einem eigenen Docker-Container mit Traefik und Let's-Encrypt-Zertifikat live geschaltet. Man kann PDFs hochladen – Stellenanzeige, Lebenslauf, Anschreiben – der Text wird automatisch daraus extrahiert und dem KI-Agenten als Kontext mitgegeben, damit die Antworten wirklich zur konkreten Bewerbung passen. Dazu kommen 19 automatisierte Tests und eine GitHub-Actions-Pipeline, damit das Projekt von Anfang an auf einem stabilen Fundament steht.

Der spannendste Moment war aber ein Bug im Live-Betrieb: beim Chatten blieb die App plötzlich einfach hängen, ohne Fehlermeldung. Grund war eine fehlerhafte Fallback-Logik auf dem Server – wenn ein Datei-Pfad falsch aufgelöst wurde, gab der Server stillschweigend eine HTML-Seite statt einer echten Fehlermeldung zurück. Das Frontend-JavaScript wusste damit nichts anzufangen und brach unbemerkt ab. Nach meiner Fehlerbeschreibung war der Fehler schnell gefunden und behoben – ein gutes Beispiel dafür, dass "es hängt einfach" oft ein sehr konkretes technisches Problem im Hintergrund hat.

Auf mein Feedback hin kamen noch ein paar Dinge dazu, die den Unterschied machen: editierbare Mappen-Details, ein "Speichern & Schließen"-Button, ein Notizen-Feld, mit dem ich den KI-Agenten pro Mappe individuell trainieren kann – meine eigenen Hinweise fließen dann direkt in seine Antworten ein – und ein Mappen-Wechsler, um schnell zwischen verschiedenen Bewerbungen zu springen. Am Ende habe ich jetzt ein Werkzeug, das mir bei der Jobsuche wirklich hilft, statt nur eine weitere Liste zu sein.

9. September 2026 Entwicklung

Luft raus: warum meine Seiten jetzt kürzer wirken

Heute habe ich mir die style.css dieser Seite vorgenommen und quer über alle Unterseiten die Abstände verkleinert – Sections, Karten, Hero-Bereich, Rechtstexte, Lebenslauf-Timeline und Gästebuch, überall zwischen 25 und 40 Prozent weniger Margin, Padding und Gap. Keine Inhalte oder Struktur angefasst, nur der Leerraum dazwischen.

Der Auslöser war simpel: Beim Durchklicken kam mir fast jede Seite unnötig lang vor, obwohl der eigentliche Inhalt gar nicht so viel ist. Die Section-Paddings standen zum Beispiel pauschal auf 80px oben und unten – auf jeder Seite, egal wie kurz der Abschnitt war. Ich habe das auf 56px reduziert, den Hero-Bereich der Unterseiten von 442px Mindesthöhe auf 340px gebracht und auch kleinere Dinge wie den Abstand zwischen Absätzen oder den Grid-Gap bei Bildergalerien und Skill-Karten angepasst. In Summe wirkt jede Seite jetzt spürbar kompakter, ohne dass sie gedrängt aussieht.

Die eigentliche Lektion kam danach: CSS-Änderungen allein reichen nicht, wenn style.css mit Cache-Busting-Parameter eingebunden ist. Ich musste anschließend in allen 20 HTML-Dateien den Query-Parameter ?v= hochzählen, sonst hätten Browser wochenlang weiter die alte, gecachte Version ausgeliefert und niemand hätte den Unterschied gesehen. Ein Detail, das man leicht vergisst, wenn man nur an der CSS-Datei selbst arbeitet – aber ohne den zweiten Schritt wäre die ganze Arbeit für die Besucher unsichtbar geblieben.

1. September 2026 Projekt

Vom Debug-Build zum Play Store

Meine Android-App EIS Schuh-Atelier ist technisch fertig für die Veröffentlichung – eigener Signierungsschlüssel, signiertes .aab, mit apksigner geprüft. Trotzdem liegt zwischen "fertig gebaut" und "im Play Store" noch ein ganzes Stück Weg, das nichts mit Code zu tun hat. Heute habe ich mir dafür einen Fahrplan mit sieben Phasen erstellt, von Rechtlichem bis Rollout.

Die Phasen im Überblick: Grundsatzentscheidung, Rechtliches, Play-Konto anlegen, Store-Eintrag gestalten, Datensicherheit-Formular ausfüllen, Technik (größtenteils schon erledigt) und zum Schluss Testen & Rollout. Am meisten überrascht hat mich, wie viel davon Papierkram ist und wie wenig Programmieren: Impressumspflicht nach §5 DDG gilt auch für eine kostenlose Hobby-App, sobald sie öffentlich im Store steht – die Ausnahme für "rein private Nutzung" greift dann praktisch nicht mehr. Dazu kommt eine Datenschutzerklärung nach DSGVO, die per URL erreichbar sein muss, und seit Februar 2025 zusätzlich ein DSA-Trader-Status in der Play Console.

Die eigentlich wichtige Entscheidung kommt aber noch vor all dem: Aktuell kann sich über die Registrierung jede beliebige Person ein Konto in meiner App anlegen. Bleibt das so, bin ich rechtlich Verantwortliche für fremde Nutzerdaten – mit vollem DSGVO-Umfang. Beschränke ich die Registrierung stattdessen auf mich selbst oder auf Einladung, sinkt das Risiko deutlich, auch wenn ein Impressum trotzdem Pflicht bleibt. Diese Entscheidung habe ich heute bewusst noch offengelassen – sie bestimmt, wie viel von Phase 1 ich wirklich brauche, und verdient es, in Ruhe getroffen zu werden statt nebenbei.

Für das Play-Konto selbst reicht mir als Hobby-Projekt ein Einzelperson-Konto (25 USD einmalig, Ausweis-Verifizierung), auch wenn das 14 Tage Closed Testing mit zwölf Testpersonen vor der Produktion verlangt. Eine Organisation mit D-U-N-S-Nummer wäre für ein Lernprojekt völlig überdimensioniert. Das ist übrigens kein Rechtsrat, nur meine eigene Recherche – Impressum und Datenschutzerklärung lasse ich im Zweifel noch von jemandem gegenchecken, der sich damit auskennt.

1. September 2026 Entwicklung

Der Fuchs zieht in die letzten beiden Zimmer

Heute habe ich Kontakt- und Gästebuch-Seite auf das einheitliche Hero-Design umgestellt, das mein Fuchs-Maskottchen trägt – Bild links, Titel und Text rechts. Damit haben jetzt alle sechs Hauptseiten meiner Website dasselbe wiedererkennbare Gesicht.

Angefangen hatte das Muster vor ein paar Wochen auf der "Wer bin ich"-Seite: ein KI-generiertes Fuchsbild links, daneben Überschrift und kurzer Text. Danach ist es Stück für Stück gewandert – zu den Projekten (ein Fuchs am Rechner), zum Blog (ein Fuchs mit Tablett) und zur Weiterbildung (ein Fuchs mit Doktorhut). Heute kamen Kontakt (ein telefonierender Fuchs am Bahnsteig) und Gästebuch (ein Fuchs, der Gäste begrüßt) dazu – beide Bilder mit Gemini erstellt und passend zum jeweiligen Seiteninhalt ausgesucht.

Technisch steckt dahinter nur eine einzige CSS-Klasse, page-hero-media, die ich einmal sauber gebaut und seitdem einfach wiederverwendet habe: Bild und Textblock stehen nebeneinander in einer Flexbox, auf dem Handy klappt das Ganze automatisch untereinander. Genau deshalb waren die letzten beiden Seiten heute auch in zwei kleinen, schnellen Commits erledigt, statt jede Seite einzeln neu zu layouten.

Meine kleine Erkenntnis dabei: Konsistenz-Arbeit wird gern aufgeschoben, weil sich jede einzelne Seite nach "nur eine Kleinigkeit" anfühlt – aber wenn man das Muster einmal richtig baut, kostet das Nachziehen der letzten Ecken kaum noch Zeit. Und ein wiederkehrendes Maskottchen gibt der Seite plötzlich eine Persönlichkeit, die reine Text-Überschriften nie hatten.

20. August 2026 Entwicklung

Vom Chip zum Dropdown: Wie ich meiner Android-App das letzte fehlende Puzzleteil eingebaut habe

Heute war ein großer Tag für mein „EIS Schuh-Atelier" – die Android-App, an der ich gerade Flutter lerne, hat zwei wichtige Meilensteine geschafft: den ersten echten Test auf einem physischen Handy und ein Feature, das ich mir schon länger gewünscht hatte.

Endlich: Test auf einem echten Gerät

Bisher lief meine App nur im Browser (Flutter Web-Modus) – praktisch zum schnellen Testen, aber eben nicht das, wofür ich sie eigentlich baue. Heute habe ich sie zum ersten Mal auf meinem Pixel 8 Pro laufen lassen, per USB-Debugging direkt vom Windows-Rechner aus.

Der komplette Kreislauf, den ich durchgespielt habe:

  • Einloggen mit meinem Test-Konto
  • Einen neuen Schuh anlegen – inklusive echtem Foto von der Handykamera
  • Nach Saison, Stil, Modell und Farbe filtern und sortieren
  • Einen Eintrag bearbeiten (Preis, Kaufdatum, Notizen)
  • Einen Eintrag wieder löschen

Alles hat auf Anhieb funktioniert. Kein CORS-Ärger wie im Browser, keine Überraschungen bei der Kamera-Integration – einfach eine App, die tut, was sie soll.

Ein Bug, der sich als Geschenk entpuppt hat

Beim Aufräumen ist mir aufgefallen, dass mein Test für den App-Start (widget_test.dart) plötzlich hängen blieb, statt einfach durchzulaufen. Der Grund: Ich hatte vor einer Weile ein „Angemeldet bleiben"-Feature eingebaut, das die Zugangsdaten verschlüsselt auf dem Gerät speichert. In der Testumgebung gibt es aber gar kein echtes Gerät – und statt sich sauber zu beschweren, blieb der Aufruf einfach für immer hängen. Ein echter Deadlock, kein netter Fehler mit Stacktrace.

Die Lösung war zum Glück einfach, sobald ich sie gefunden hatte: Ich musste dem Test eine Fake-Version des Speichers unterschieben, genau wie ich es bei anderen Netzwerkzugriffen schon mache. Danach liefen wieder alle 40 Tests grün durch.

Das Merkmale-Feature: Backend und App gemeinsam

Der zweite Teil des Tages war größer: Ich wollte schon länger die Merkmale eines Schuhs (Größe, Saison, Stil, Modell, Farbe) auch nachträglich ändern können – bisher konnte man die nur beim Anlegen festlegen, danach waren sie eingefroren.

Das Problem: Mein Backend (eine separate FastAPI-Anwendung, die auch meine Web-App versorgt) kannte dieses Feld beim Aktualisieren eines Eintrags gar nicht. Also musste ich zum ersten Mal in dieser Session auch am Backend arbeiten:

  1. Backend-Repo geklont und den PUT /update-ordner-Endpunkt um ein merkmale-Feld erweitert – genau nach dem Muster, das beim Neuanlegen schon existierte.
  2. Isoliert getestet, gegen eine separate Test-Datenbank auf meinem Server, bevor überhaupt irgendetwas an die echte, produktive App ging. Sicher ist sicher.
  3. Deployed – was sich als kleines Abenteuer entpuppte, weil der automatische Reload meines Servers die Codeänderung aus irgendeinem Grund nicht selbst aufgegriffen hat. Ein kurzer, gezielter Neustart des Containers hat's dann aber gebracht.
  4. Live verifiziert, mit meinem Test-Konto: Eintrag anlegen, Merkmale ändern, prüfen, wieder aufräumen.

Erst danach ging's an die App-Seite: Aus der reinen Anzeige der Merkmale (kleine Chips, nicht anklickbar) wurden fünf richtige Dropdown-Felder im Detail-Screen – genau wie ich sie schon beim Anlegen eines neuen Schuhs verwende. Wer ein altes Merkmal ändern will, tippt einfach das Dropdown an und wählt einen neuen Wert.

Was ich mitnehme

Der Tag hat mir nochmal gezeigt, wie viele kleine Bausteine so eine App eigentlich hat: UI, Service-Schicht, Backend-Endpunkt, Datenbank, Tests auf mehreren Ebenen, und dann noch die Deployment-Infrastruktur dahinter. Besonders gemerkt habe ich mir: immer zuerst gegen eine isolierte Testumgebung prüfen, bevor irgendwas an eine live laufende Anwendung geht – auch wenn's die eigene Hobby-App ist.

Als Nächstes steht bei mir an, die kaputte CI/CD-Pipeline meines Backends aufzuräumen (sie zeigt aktuell auf einen Branch, den es gar nicht gibt – läuft also nie automatisch). Aber das ist eine Geschichte für einen anderen Tag.

20. August 2026 Entwicklung

Blueberry trifft Cream Soda: Ein Farbtest nur für die Startseite

Heute habe ich mich getraut, mit der Farbwelt von eiskopani zu spielen. Nur auf der Startseite, nur zum Testen: Kopfzeile, Hero und Kontaktbereich in einem satten Blau ("Blueberry", #243B8F), der Rest in einem warmen Cremeton ("Cream Soda", #FFF0C9) – ohne dass ich dafür das komplette Design der Seite anfassen musste.

Der Trick dabei: Statt die zentrale style.css zu ändern, die für die ganze Website gilt, habe ich in der index.html einen kleinen, extra gekennzeichneten Style-Block eingefügt, der nur dort wirkt. Damit kann ich risikofrei ausprobieren, wie sich neue Farben anfühlen, ohne dass Blog, Projekte- oder Weiterbildungsseite plötzlich anders aussehen. Fällt mir der Test nicht zu, lösche ich einfach die paar Zeilen wieder – die restliche Seite bleibt unberührt. Eine kleine, aber angenehme Erkenntnis: Man muss nicht gleich das ganze Haus umstreichen, um zu wissen, ob einem eine Farbe gefällt.

Nebenbei ist heute auch der Kurs-Badge auf der Weiterbildungsseite konkreter geworden: Aus "Geplant" für den IHK-Zertifikatslehrgang Technische/-r KI-Manager/-in ist jetzt "Start 23.11.2026" geworden. Kleiner Textwechsel, aber für mich ein gutes Gefühl – aus einer vagen Absicht wird ein festes Datum im Kalender.

12. August 2026 Entwicklung

Von "Neu" zu "Live" – und die Abschlussdoku gleich mit dazu

Zweite kleine Aufräumrunde heute an der Desktop-App: Der Badge auf der Projekte-Seite heißt jetzt nicht mehr „Neu", sondern „Live" – und direkt neben dem Download der .exe-Datei gibt es jetzt auch einen Button für meine offizielle IHK-Projektdokumentation als PDF.

Klingt nach Kleinkram, war für mich aber ein kleiner Meilenstein-Moment. Die Desktop-Version des Schuh-Ateliers lief schon eine Weile stabil, trug aber immer noch das Etikett „Neu" – als wäre sie gerade erst aus der Werkstatt gekommen. Jetzt, wo ich weiß, dass sie zuverlässig läuft und ich sie selbst benutze, habe ich mich getraut, den Status zu ändern. Ein Badge ist ja nichts Technisches, sondern ein Versprechen an Besucher:innen der Seite: „Das hier kannst du dir anschauen, das ist fertig." Diesen Schritt bewusst zu gehen, fühlte sich ehrlicher an, als eine App ewig als „neu" laufen zu lassen.

Die IHK (Industrie- und Handelskammer) verlangt für die Abschlussprüfung eine schriftliche Projektdokumentation – bei mir dreht sich die um genau dieses Schuh-Atelier-Projekt. Bisher lag die PDF nur bei mir auf der Platte. Jetzt liegt sie, neben Hero-Bereich und Fazit der Desktop-Seite, direkt neben dem App-Download – für alle sichtbar, die nicht nur sehen wollen, was ich gebaut habe, sondern auch, wie ich es begründet und dokumentiert habe. Zwei Zeilen Code, aber ein Türöffner mehr.

12. August 2026 Projekt

Nach Web und Desktop jetzt aufs Handy: Das Schuh-Atelier lernt Flutter

Heute habe ich dem EIS Schuh-Atelier eine dritte Gestalt gegeben: Nach der Web-App und der Windows-Desktop-App kommt jetzt eine eigene Android-App dazu. Ich habe dafür eine neue Projektseite gebaut und meine Projekte-Übersicht gleich mit aufgeräumt, damit sie zu den inzwischen elf Projekten passt.

Für die Android-Version steige ich in Flutter und Dart ein – komplettes Neuland für mich. Reizvoll finde ich, dass ich mit einer einzigen Codebasis eine native App fürs Handy bauen kann, und dass sie sich am Ende wie eine kleine Familie mit der Desktop-App anfühlen soll: gleiches dunkles Holzbraun-Gold-Design, gleiches Backend im Hintergrund. Schuhe erfassen, Foto pro Eintrag, Live-Suche, Kaufdatum und Schätzwert – die Liste der geplanten Funktionen kenne ich schon aus den anderen Versionen, nur die Sprache und der Bildschirm sind neu.

Beim Aufräumen der Projekte-Seite ist mir aufgefallen, dass ich mit der Zeit angefangen hatte, mich selbst zu wiederholen: Es gab oben eine Extra-Sektion „Was läuft gerade?“ mit vier Kacheln, die dieselben Themen noch einmal zusammenfasste, die weiter unten als eigene Projektkarten schon längst existierten. Die habe ich komplett entfernt und stattdessen alle elf Projekte sauber in eine einzige, durchnummerierte Reihenfolge gebracht. Eine Übersicht ist nur dann eine Übersicht, wenn sie nicht zwei verschiedene Versionen derselben Wahrheit erzählt.

10. August 2026 Entwicklung

Die Galerie war fertig – nur die Lupe fehlte

Heute habe ich auf meiner Hobbys-Seite eine neue Sektion gebaut: „Meine Lieblings-KI-Bilder", fünf Bilder zum Anklicken und Vergrößern. Alles sah gut aus, das Grid stand, die Bilder luden – und trotzdem passierte beim Klick auf ein Bild: nichts. Keine Fehlermeldung, kein Absturz, einfach gar keine Reaktion.

Für die Vergrößerung nutze ich ein kleines JavaScript-Werkzeug namens GLightbox – es öffnet angeklickte Bilder groß in einer Art Dia-Show über der Seite. Das Skript dafür war eingebunden und lief auch technisch korrekt. Was fehlte, war eine einzige Zeile: die passende CSS-Datei, die dem Werkzeug sagt, wie die vergrößerte Ansicht überhaupt aussehen soll. Ohne sie hat GLightbox im Hintergrund brav funktioniert, aber alles war unsichtbar – kein Rahmen, keine Überlagerung, keine Animation. Ein Feature, das komplett fertig gebaut, aber für niemanden sichtbar war.

Der Fix war am Ende trivial: eine `link`-Zeile im Header ergänzt, die die GLightbox-CSS lädt. Die eigentliche Lektion war eine andere: Ich hatte nach dem Bauen nur geprüft, ob das Grid und die Bilder da sind – nicht, ob die Interaktion, die den ganzen Sinn der Sektion ausmacht, auch wirklich klickbar ist. „Sieht fertig aus" und „funktioniert wie gedacht" sind zwei verschiedene Dinge, und nur das zweite zählt für die Besucher meiner Seite.

10. August 2026 Erkenntnis

„Wie soll ich dabei was lernen?" – ein Satz, der mich gestoppt hat

Meine Flutter-App ist heute zwei Schritte weitergekommen: Der Register-Screen ist fertig, und gleich danach der Katalog-Screen, der meine Schuh-Sammlung als Kachel-Übersicht zeigt. Eigentlich ein guter Tag. Aber der eigentliche Lernmoment war ein anderer – und der hatte nichts mit Code zu tun.

Zwischendurch ist mir aufgefallen, dass ich nur noch Ergebnisse abgenickt habe: „passt", „weiter", nächster Schritt. Also habe ich kurz gebremst und gesagt, dass mir das so nichts bringt – wenn ich nur zusehe, wie fertiger Code entsteht, lerne ich kein Flutter, sondern trainiere mich höchstens im Zustimmen. Der Code war ja sogar ausführlich auf Deutsch kommentiert, aber im Gespräch selbst kamen die Erklärungen zu kurz, weil viele Schritte einfach zügig hintereinander liefen.

Danach wurde es besser: vor jedem Bauschritt kurz erklärt, welches Flutter-Konzept gerade dran ist und warum – etwa, dass der Register-Screen einen Navigations-Bug hatte, weil der „Zurück"-Pfeil einen alten Login-Screen im Verlauf noch fand, obwohl ich schon angemeldet war. Erst als das benannt wurde, habe ich wirklich verstanden, warum die Lösung heißt: den gesamten alten Verlauf löschen statt nur eine Seite zu ersetzen. Kleine Sache, aber genau der Unterschied zwischen „App funktioniert jetzt" und „ich weiß jetzt auch, warum".

10. August 2026 Weiterbildung

Mein erster Login-Screen – und eine Überraschung beim Testen

Ich baue gerade eine Android-Version meiner Schuh-Galerie, um dabei Flutter zu lernen – learning-by-doing statt trockener Grundkurs. Heute ist der Login-Screen fertig geworden: Benutzername und Passwort eintippen, die App fragt beim bestehenden Server nach, und bei Erfolg geht's weiter. Klingt simpel, war aber mein erster richtiger Ausflug in Ladezustände, Fehlermeldungen und Server-Kommunikation in einer echten App.

Ein Konzept, das mir besonders eingeleuchtet hat: Man baut den Screen so, dass er nicht fest an den echten Server gekoppelt ist, sondern der "Dienst", der die Anfragen verschickt, von außen hineingereicht werden kann. Für Tests ersetzt man ihn dann einfach durch eine Attrappe, die vorgibt, ein Server zu sein – ohne dass man wirklich einen erreichen muss. So laufen alle Tests schnell und zuverlässig, auch offline.

Die eigentliche Überraschung kam beim manuellen Test im Browser: Flutter zeichnet seine komplette Oberfläche als eine Art Bild (Canvas), nicht als normale Webseite mit anklickbaren Textfeldern und Knöpfen. Ein Testwerkzeug, das sonst nach Buttons "mit dem Namen Login" sucht, findet dort schlicht nichts – man muss stattdessen auf exakte Pixel-Koordinaten klicken. Ein kleiner Moment, der mir gezeigt hat, wie unterschiedlich "im Browser laufen" für eine Flutter-App und eine normale Website eigentlich bedeutet.

5. August 2026 Gedanken

Kennzeichnungspflicht für KI – und warum ich sie längst freiwillig befolge

Seit dem 2. August 2026 gelten in der EU die Transparenzpflichten des AI Act – des ersten großen KI-Gesetzes der Welt. Kurz gesagt: Wer Inhalte von einer KI erzeugen lässt – Texte, Bilder, Stimmen, Videos – muss das unter bestimmten Umständen kenntlich machen. Als jemand, der KI täglich als Werkzeug nutzt, habe ich mir die Regeln genauer angesehen.

Grob gibt es zwei Richtungen. Anbieter von KI-Systemen müssen ihre synthetischen Ausgaben maschinenlesbar markieren – also so, dass auch andere Programme erkennen können: Das kommt von einer KI. Und wer KI-Inhalte veröffentlicht – etwa täuschend echte „Deepfakes" oder KI-Texte zu Themen von öffentlichem Interesse – muss offenlegen, dass sie künstlich erzeugt wurden. Auch Chatbots müssen sagen, dass man mit einer Maschine spricht, wenn es nicht ohnehin offensichtlich ist. Für erkennbar künstlerische oder satirische Werke gibt es Ausnahmen. (Ich bin keine Juristin – das ist mein Verständnis als Nutzerin, keine Rechtsberatung.)

Für mich ändert das wenig – und das freut mich. Meine KI-Musikexperimente mit Suno, die KI-Experimente-Seite, sogar große Teile dieser Website sind mit KI-Unterstützung entstanden, und ich schreibe das offen dazu. Ich sehe Kennzeichnung nicht als Bürde, sondern als Ehrlichkeit: Wer mein Portfolio liest, soll wissen, wo ich selbst Hand angelegt habe und wo eine KI mein Werkzeug war. Transparenz nimmt der Technik nichts – sie gibt ihr Vertrauen.

5. August 2026 Entwicklung

28 echte Zertifikate ziehen ein – die Platzhalter-Idee zahlt sich aus

Vor zwei Wochen hatte ich eine Zertifikate-Seite gebaut, die mit 20 Platzhaltern funktioniert und sich automatisch aktualisiert, sobald ich echte PDFs nachliefere. Heute war es so weit: Ich habe alle Nachweise zusammengesucht, gescannt und hochgeladen – 28 echte Dateien statt der alten Platzhalternamen wie zertifikat-3.pdf. Und die Seite hat sie sich, wie geplant, einfach selbst gezogen.

Der größere Umbau passierte auf der „Wer bin ich?"-Seite: Aus einer losen Liste wurde ein Karten-Grid mit 32 Karten in sechs Kategorien – Abschlüsse & Prüfungen, Künstliche Intelligenz & Entwicklung, Microsoft Power Platform, Requirements Engineering & Agile, und so weiter.

Kniffliger als gedacht war das Verlinken selbst: Viele Original-Dateinamen enthalten Leerzeichen und Umlaute („Copilot Führerschein - Power Apps.pdf"), und Browser mögen solche Zeichen in Links nicht. Also mussten alle Pfade URL-kodiert werden – Leerzeichen werden zu %20, „ü" zu %C3%BC und so weiter. Am Ende habe ich alle 28 Live-Links noch einmal einzeln per HTTP-Anfrage geprüft, ob der Server wirklich mit „gefunden" antwortet, bevor ich hochgeladen habe. Nichts ist ärgerlicher als eine Zertifikate-Seite voller Links, die ins Leere laufen.

22. Juli 2026 Entwicklung

Eine Zertifikate-Seite, die sich selbst aktualisiert

Heute habe ich meine Website etwas aufgeräumt: Die Lieblingsvideos und der Text über meine Musik-Experimente mit Suno sind von der Startseite in die Hobby-Seite gewandert, und der Abschnitt „Was läuft gerade?" ist von „Wer bin ich?" zur Projekte-Seite gezogen. Klingt banal, war aber überfällig – Inhalte sollten dort stehen, wo Besucher sie thematisch erwarten, nicht dort, wo sie zufällig zuerst entstanden sind.

Der eigentliche Kern des Tages war aber eine neue Seite: zertifikate.html, eine Galerie für alle meine Zertifikate und Seminarnachweise. Jede Karte zeigt eine PDF-Vorschau, und ein Klick vergrößert sie über eine „Lightbox" (ein Overlay-Fenster, das das Dokument groß über der Seite anzeigt, ohne dass man die Seite verlässt). Bisher habe ich aber noch nicht alle 20 Zertifikate als Datei vorliegen – also musste die Seite auch mit Lücken funktionieren, ohne dass ich sie später nochmal anfassen muss.

Die Lösung: Für jede der 20 Karten schickt das Skript im Hintergrund eine kurze Anfrage ("HEAD-Request") an den erwarteten Dateipfad, um zu prüfen, ob die PDF schon existiert – ohne sie komplett herunterzuladen. Antwortet der Server mit „gefunden", ersetzt das Skript den Platzhalter automatisch durch die echte Vorschau. Antwortet er mit „nicht gefunden", bleibt einfach ein kleines Papier-Symbol mit „folgt" stehen. Das Ergebnis: Ich kann in den nächsten Wochen einfach PDFs in einen Ordner legen, benannt nach einem festen Schema, und die Seite zieht sie sich selbst – kein Code-Update, kein erneutes Deployment nötig.

Die kleine Erkenntnis dahinter: Es lohnt sich, eine Seite so zu bauen, dass unvollständige Daten kein Blocker sind. Statt zu warten, bis alle 20 Zertifikate eingescannt sind, existiert die Struktur schon heute – und füllt sich von allein, sobald die Dateien nach und nach dazukommen.

4. Juli 2026 CI/SecCD

Ein Not-Passwort ist schlimmer als gar keins

Heute nur eine einzige Zeile Code geändert – aber sie hatte es in sich. Im Backend vom Whisky-Kuratorium hing der Login seit Monaten an einem Fallback-Secret, das direkt im Quellcode stand. Fehlte die Umgebungsvariable mit dem echten Passwort, sprang stillschweigend ein Ersatzwert ein – mitsamt dem Kommentar „DO_NOT_USE_IN_PRODUCTION", den in dem Moment niemand mehr liest.

Zum Hintergrund: Ein JWT (JSON Web Token) ist so etwas wie ein digitaler Ausweis, den sich der Server nach dem Login selbst ausstellt. Damit niemand einen falschen Ausweis fälschen kann, wird er mit einem geheimen Schlüssel signiert – dem SECRET_KEY. Im Code stand bisher os.getenv("JWT_SECRET", "FALLBACK_SECRET_DO_NOT_USE_IN_PRODUCTION"). Das klingt harmlos, ist aber ein stiller Notausgang: Wird die Umgebungsvariable beim Deployment aus Versehen nicht gesetzt, stürzt nichts ab – die App läuft einfach weiter und signiert Logins mit einem Wort, das jeder im öffentlichen Git-Verlauf lesen kann. Wer den Code kennt, kann sich gültige Tokens selbst basteln.

Die Lösung ist absichtlich unbequem: SECRET_KEY = os.environ["JWT_SECRET"] – ohne Fallback. Fehlt die Variable jetzt, wirft Python sofort einen KeyError und die App startet gar nicht erst. Das nennt sich „Fail Fast": lieber ein lauter Absturz beim Deployment als ein leiser Sicherheits-Kompromiss im Betrieb. Dazu habe ich das echte Produktions-Secret rotiert, falls der alte Fallback-Wert doch irgendwo aktiv war.

Die eigentliche Erkenntnis: Ein Ein-Zeilen-Diff sagt nichts über seine Wichtigkeit aus. Während ich nebenbei an einem größeren Feature für die Kassenbon-Funktion in LernyTube saß, bin ich über diese Altlast gestolpert – und es hat sich gelohnt, kurz abzubiegen und sie sofort zu fixen, statt sie auf die To-do-Liste zu schieben.

27. Mai 2026 KI & Automatisierung

Reddit hat gelogen – aber das RAG funktioniert trotzdem

Ein Reddit-Post versprach: NotebookLM als kostenloses RAG-Backend in Claude Code, inklusive Mindmaps und Quizzes per MCP-Wrapper. Ich habe es ausprobiert. Der Post hatte halb Recht – und halb nicht. Das Ergebnis ist trotzdem das Nützlichste, was ich diese Woche gebaut habe.

RAG bedeutet grob: dem KI-Assistenten eigene Dokumente als Nachschlagewerk geben, damit er aus echten Quellen antwortet statt aus seinem Trainingsgedächtnis. NotebookLM ist Googles Tool dafür – man lädt Texte oder URLs hoch, und es indiziert sie. Der MCP-Wrapper verbindet das mit Claude Code, sodass Claude direkt in NotebookLM suchen kann, ohne den Chat verlassen zu müssen.

Ich habe zwei Wrapper verglichen und mich für jacob-bd/notebooklm-mcp-cli entschieden (Python, 39 Tools). Installation: pip install notebooklm-mcp-cli, dann nlm login (öffnet den Browser für Google-OAuth), dann nlm setup add claude-code – das legt den MCP-Eintrag automatisch in der Claude-Konfiguration an. Nach einem Neustart zeigt /mcp den Server als „connected" mit 39 Tools. Kein manuelles JSON-Editieren nötig.

Der Live-Test: Notebook „LernyTube Dokumentation" angelegt, mein GitHub-Repo als einzige Quelle indiziert. Frage an Claude: „Welche Datenbank nutzt LernyTube?" – Antwort: „MongoDB", mit direktem Zitat auf die Tech-Stack-Tabelle in der README. Kein Raten, kein Halluzinieren – echtes Nachschlagen. Das hat mich ehrlich überrascht, wie schnell das end-to-end lief.

Was der Reddit-Post verschwieg: Mindmaps und Quizzes unterstützt keiner der populären Wrapper. Nur Audio Overviews (das gesprochene Zusammenfassungs-Feature von NotebookLM). Es gibt einen Wrapper mit 20 Stars, der das angeblich kann – aber 20 Stars heißt: kaum jemand hat es ernsthaft getestet. Ich hab's gelassen. Außerdem: Google sieht alles, was hochgeladen wird – also keine sensiblen Geschäftsdaten rein. Und die Auth-Cookies laufen alle zwei bis vier Wochen ab, dann ist ein erneutes nlm login nötig. Kleiner Aufwand, kein Drama, weil das Setup lokal auf meinem Windows-Laptop läuft und nicht auf dem VPS – Browser ist einfach da.

Mein Fazit: Den Hype ignorieren, die Technik selbst prüfen. RAG aus Claude Code heraus funktioniert und ist für mein Lerntempo gerade genau richtig – ich kann Fragen zu eigenem Code stellen, ohne alles im Kontext mitzuschleppen.

18. Mai 2026 KI & Automatisierung

Der Agent, der selbst entscheidet, ob er schreibt

Heute habe ich einen kleinen Agenten fertiggestellt, der diese Website mitschreibt – buchstäblich. Er prüft zunächst selbst, ob überhaupt etwas Blogwürdiges passiert ist, bevor er auch nur einen Satz formuliert. Kein Material, kein Post. Fertig.

Das klingt selbstverständlich, ist es aber nicht. Die meisten Automatisierungen, die ich bisher gebaut habe, tun einfach, was man ihnen sagt – immer, bedingungslos, egal ob es sinnvoll ist. Dieser Agent hat eine Selbstprüfung eingebaut: Er schaut nach Git-Commits, geänderten Dateien, Session-Notizen. Wenn weniger als zwei Commits oder fünf relevante Dateiänderungen vorliegen, schweigt er. Das Tageslimit von drei Posts pro Tag respektiert er ebenfalls – und prüft es aktiv, bevor er weitermacht.

Die eigentliche Arbeit war das Prompt-Design: dem Agenten beizubringen, wann „genug" genug ist, und wie er das Datum auf Deutsch formatiert (das System liefert englische Monatsnamen – eine kleine Falle, in die man leicht tappt). Dazu gehört auch das genaue HTML-Template für die Blog-Karte, damit neue Einträge strukturell zu den alten passen und der Auf/Zuklapp-Mechanismus korrekt funktioniert.

Was ich dabei gelernt habe: Ein Agent wird erst dann nützlich, wenn er auch „Nein" sagen kann. Ein Werkzeug, das immer einen Output produziert, erzeugt Rauschen. Eines, das erst prüft und dann handelt, erzeugt Signal. Dieser Unterschied klingt philosophisch, macht in der Praxis aber den ganzen Unterschied.

18. Mai 2026 Erkenntnis

Warum ein Kassenbon das ehrlichste Feedback der Welt ist

Ich habe heute über etwas nachgedacht, das jeder kennt und keiner beachtet: den Kassenbon. Sekunden nach dem Bezahlen liegt da ein Stück Papier mit einer brutal ehrlichen Zusammenfassung – Datum, Position, Menge, Summe. Kein Geschwafel, kein „demnächst", keine Ausreden. Das ist eines der wirkungsvollsten Feedback-Formate, die wir im Alltag haben – und ich habe es heute zu einem Lern-Werkzeug umgebaut.

Hintergrund: Ich arbeite an meinem Lern-Projekt LernyTube, einer kleinen Plattform, in der ich YouTube-Videos in echten Lern-Sessions strukturiere, Notizen mache und Snapshots setze. Das funktioniert gut – aber am Ende einer Session ist mein Kopf voll, und das Wichtigste verflüchtigt sich, wenn ich es nicht sofort festhalte. Ein freies Tagebuch hilft mir da nicht: zu viel Spielraum, zu wenig Druck zur Verdichtung.

Deshalb gibt es jetzt am Session-Ende einen Lern-Kassenbon. Fünf Felder, mehr nicht: Dauer, Konzentration, was konkret entstanden ist, die eine Erkenntnis, und der nächste Schritt. Der Bon sieht aus wie ein echter Kassenzettel – Monospace-Schrift, Papier-Optik, gezackte Kante. Das ist nicht Deko, sondern Tonfall: Der Stil sagt „kurz, ehrlich, fertig" – und genau so möchte ich nach einer Session reflektieren.

Der spannendste Teil sind die Smart-Defaults: Die Dauer schätzt das System aus dem Abstand zwischen erstem und letztem Snapshot – ich muss nur korrigieren, nicht raten. Die Erkenntnis-Zeile wird mit dem Text der letzten Snapshot-Notiz vorbelegt – meistens ist genau dort schon das Wichtigste formuliert, ich muss es nur bestätigen oder verdichten. Die Hürde, den Bon zu erstellen, ist damit auf zwei Klicks geschrumpft – und genau deshalb wird er auch tatsächlich genutzt.

Was bleibt als Erkenntnis: Verdichtung ist anstrengender und wertvoller als freies Schreiben. „Was bleibt hängen?" in einem Satz ist ein härteres Werkzeug als drei Absätze Tagebuch. Und gute UX-Patterns finde ich nicht in Tech-Blogs, sondern an der Supermarkt-Kasse.

11. Mai 2026 KI & Automatisierung

Zehn kleine Assistenten – und ein Türsteher

Ich habe heute meinem KI-Assistenten ein Team gegeben. Statt einem Allrounder, der alles ein bisschen kann, gibt es jetzt zehn Spezialisten – jeder mit einer klar umrissenen Aufgabe und genau den Werkzeugen, die er dafür braucht.

Vier davon sind global, also in jedem Projekt verfügbar: ein Secret-Auditor, der vor jedem Push die gesamte Git-Historie nach Passwörtern und API-Keys durchforstet. Ein Safe-Backup, das vor riskanten Operationen schnell einen lokalen Commit anlegt. Ein CI-Predictor, der die GitHub-Workflows einmal mental durchspielt, bevor ich pushe – damit ich nicht reaktiv auf rote Builds reagieren muss. Und ein Deletion-Guardian, mein Lieblings-Agent: ein digitaler Türsteher, der bei jedem rm -rf oder DROP TABLE zuerst klassifiziert, was gelöscht werden soll, und im Zweifel einfach stoppt.

Dazu kamen sechs projekt-spezifische Helfer: Tester für Whisky-Kuratorium, LernyTube und EIS Schuh-Atelier, ein Excel-Importer für die Whisky-Vorlage, und für vita.eiskopani.de gleich zwei – einer für die Playwright-Tests, einer der direkt zu Hostinger deployt, ohne Rückfragen. Der zehnte ist der Blog-Autor: er entscheidet selbst, ob heute genug passiert ist, prüft mein Tageslimit (maximal drei Beiträge), und postet erst, wenn die HTML-Struktur konsistent ist. Er hängt am Session-Ende-Hook und meldet sich anschließend per Telegram.

Die Erkenntnis, die mich heute am meisten gefreut hat: ein Türsteher schlägt einen Schadensbegrenzer. Lieber einmal mehr stoppen als einmal zu viel löschen.

29. April 2026 CI/SecCD

Tests grün heißt nicht sicher – was mir der Audit beigebracht hat

Für mein neues Umfrage-Projekt hatte ich 67 Tests, davon 26 explizit als Security-Tests, dazu Bandit (statische Code-Analyse) und Safety (CVE-Scan) im GitHub-Actions-Pipeline. Alles grün. Trotzdem fragte mich der User: „Hast du an die Sicherheit gedacht?" – und hatte recht.

Die unangenehme Wahrheit: Tests prüfen nur, was sie testen. Sie ersetzen keinen Audit. Konkret hatte ich drei Lücken übersehen:

1. Der echte Anthropic-API-Key stand im Klartext in der docker-compose.yml. Nicht im Git-Repo, aber jeder mit Server-Zugriff hätte ihn lesen können. Fix: Schlüssel in eine .env mit chmod 600, im Compose nur noch ${ANTHROPIC_API_KEY} referenziert. Gleiches gilt für das DB-Passwort.

2. XSS im Frontend. Der KI-Output (Kernaussage, Stichworte, Bewertung) wurde direkt per innerHTML in das Dashboard gerendert. Wenn ein User in seine simulierte E-Mail <script>-Tags einschmuggelt und Claude diese im extrahierten Text spiegelt – Code-Ausführung im Browser. Fix: eine winzige esc()-Funktion, die HTML-Sonderzeichen escapt, und konsequent vor jedem dynamischen Wert anwenden.

3. Keine Schutz-Header. Keine Content-Security-Policy, kein X-Frame-Options, kein X-Content-Type-Options, keine Referrer-Policy. Fix: eine FastAPI-Middleware, die alle vier auf jede Antwort setzt – fünf Zeilen Code.

Was ich daraus mitnehme: Security-Audit ist eine eigene Phase, kein Nebenprodukt grüner Tests. Tests sichern App-Logik ab – Deployment-Artefakte (Compose, .env, Workflows) und Frontend-Rendering müssen separat durchgesehen werden. Ich habe dafür jetzt eine eigene Memory-Regel angelegt: „Bandit/Tests grün ≠ sicher; docker-compose, .env, Frontend-XSS, HTTP-Header explizit prüfen."

Bonus-Lektion am gleichen Tag: Drei Push-Zyklen, weil ich nach jedem CI-Fehler einzeln gefixt habe statt vorher den Workflow + die Repo-Struktur einmal zu lesen. Auch das ist jetzt eine Memory-Regel. Manchmal ist die teuerste Zeit die, in der man sich für „schnell mal pushen" entscheidet.

27. April 2026 KI-Projekt

Wie ich eine E-Mail-Umfrage-Orchestrierung gebaut habe – ohne eine einzige echte E-Mail

Ausgangslage: Ein Use-Case aus dem öffentlichen Sektor, in dem iterativ E-Mail-Umfragen an Seminar-Teilnehmer rausgehen sollen. Antworten kommen frei formuliert zurück, eine KI extrahiert daraus strukturierte Daten, ein Mensch bestätigt – und überfällige Fälle werden eskaliert. Frage: Lässt sich so etwas als Prototyp bauen, ohne sofort an Outlook und SMTP zu hängen?

Antwort: Ja, wenn man das E-Mail-System komplett simuliert. Die KI-Extraktion bleibt echt (Claude Haiku 4.5), alles andere – Versand, Posteingang, Antwort – passiert im Browser. Damit lässt sich der gesamte Workflow demonstrieren, ohne externe Abhängigkeiten.

Architektur: FastAPI + PostgreSQL im Docker-Container, fünf Tabellen (Umfragen, Teilnehmer, Zuordnung, Antworten, Seminar-Referenzen), ein einseitiges Vanilla-JS-Dashboard. Jede Umfrage bekommt eine ID im Format UMF-2026-001. Wer eine Antwort simuliert, gibt sie als „E-Mail" mit dieser ID im Betreff ein – das System parst die ID per Regex, schickt den Freitext an Claude und speichert das JSON-Resultat als JSONB.

Human-in-the-Loop: Jede KI-Extraktion landet zuerst im Status PENDING. Erst nach manueller Freigabe geht die Antwort in die Auswertung – wird sie abgelehnt, ist die Extraktion verworfen. Ein simpler, aber wichtiger Schritt: Die KI ist hier ein Vorschlag, kein Urteil.

Eskalation: Ein zusätzlicher Endpoint /eskalieren findet alle überfälligen Versendungen (Frist überschritten, keine Antwort) und markiert sie. Das passt gut zum Use-Case, in dem regelmäßig Erinnerungen rausgehen müssen.

Tests: 18 Unit-Tests (ID-Generierung, Betreff-Parsing, KI-Output-Validierung), 23 Integrationstests gegen eine echte Postgres-Test-DB (alle API-Endpunkte), 26 Security-Tests (SQL-Injection-Payloads, Input-Validierung, HTTP-Methoden, XSS-Regression, Schutz-Header). Dazu Bandit für statische Code-Analyse und Safety für CVE-Checks – alles in einer GitHub-Actions-Pipeline mit vier parallelen Jobs.

Das Schöne an dem Ansatz: Wenn Outlook oder ein anderer Mail-Connector irgendwann tatsächlich angedockt werden muss, ist das nur eine Eingangsroute mehr. Die Logik dahinter – Parsen, KI-Extraktion, Review, Eskalation – bleibt unverändert. Simulation war hier kein Notnagel, sondern die ehrliche Antwort auf die Frage, welcher Teil der Wertschöpfung tatsächlich neu ist: nicht das Versenden, sondern das Verstehen der Antworten.

23. April 2026 Security

Idempotency Key, Rate-Limit, Throttling – was davon brauche ich wirklich?

In meinem Notizbuch standen drei Begriffe, die mir in einem Interview-Kontext begegnet waren: Idempotency Key, Rate Limit, IP-Throttling. Klang wichtig. Aber brauche ich das für meine drei kleinen Projekte überhaupt?

Also erst mal sortiert: Ein Idempotency Key sorgt dafür, dass ein doppelt abgeschickter Request nicht zweimal ausgeführt wird – klassisch bei Zahlungen, damit 50 € nicht versehentlich zweimal abgebucht werden. Da ich keine Payment-Flows habe, fällt das weg. Rate-Limit und IP-Throttling dagegen schützen öffentliche Endpoints vor Brute-Force und Flood-Angriffen – und genau das hat mir gefehlt.

Der kritische Punkt auf meinem Server ist der Musik-Upload-Proxy (FastAPI + SFTP), über den die Admin-Seite MP3-Dateien auf Hostinger schickt. Er ist zwar per Bearer-Token geschützt, aber SHA-256 ist schnell zu brute-forcen, und bei jedem fehlgeschlagenen Versuch würde der Server bis zu 50 MB Upload-Body entgegennehmen, bevor überhaupt die Auth greift. Klassisches DoS-Risiko.

Die Lösung: Rate-Limit-Middleware direkt auf Traefik-Ebene – kein Code-Rebuild nötig, blockt schon, bevor der große Body durchkommt. Vier Zeilen im docker-compose.yml: average=20, period=1m, burst=40 pro IP. Für mich beim Hochladen völlig unkritisch – für einen Angreifer bedeutet das, dass Brute-Force auf den Token statistisch unmöglich wird.

Seitenfund beim Reinschauen ins docker-compose.yml: Das SFTP-Passwort stand dort im Klartext. „Nicht heute" habe ich kurz gedacht – dann korrigiert vom User: „Warum nicht heute?" Gute Frage, kein guter Grund. Also gleich hinterher: Passwort in eine .env-Datei mit chmod 600, .gitignore daneben, env_file-Referenz im Compose-File. Damit ist auch ein späterer Git-Push des Verzeichnisses safe.

Lektion: Security-Fachbegriffe sind keine Checkliste, die man komplett abhaken muss. Erst verstehen, welches Problem sie lösen, dann prüfen, ob man dieses Problem überhaupt hat. Und wenn man dann doch etwas absichert: richtig, nicht halb.

22. April 2026 Infrastruktur

Ein zentraler MCP-Hub – und warum Ollama wieder rausflog

Gestern waren zwei Themen dran: Ich wollte, dass jede Claude-Session direkt auf alle meine Projekte zugreifen kann, ohne dass ich jedes Mal den Kontext erkläre. Und ich wollte meine Telegram-Pipeline endlich stabil bekommen – bis dahin stolperte sie regelmäßig über RAM-Fehler.

Lösung für Teil eins: ein eigener MCP-Hub-Server unter mcp.eiskopani.de. MCP steht für Model Context Protocol – der Standard, über den Claude Tools von außen einbinden kann. Der Hub läuft als Docker-Container, hat die vier Projektverzeichnisse (LernyTube, Whisky, EIS, vita) read-only eingebunden und stellt Tools bereit wie list_projects, read_project_file oder run_shell. Jede neue Claude-Session kennt ab sofort alle Projekte automatisch. Authentifizierung per Secret im URL-Query, HTTPS via Traefik + Let's Encrypt.

Teil zwei war härter. Meine Telegram-Pipeline – ich schicke eine Nachricht ans Bot, und Claude Code erledigt die Aufgabe auf dem Server – hatte bisher ein Zwischenglied: Ein lokales Ollama-Modell (Qwen 2.5 Coder 7B) sollte die Nachricht in einen strukturierten Task formatieren. Klang clever, war in der Praxis aber ein Problem: Das Modell braucht 4,3 GB RAM, mein VPS hat nur 3,4 GB frei. Jeder zweite Aufruf endete mit Memory-Error.

Die ehrliche Erkenntnis: Claude Code selbst ist das smarte LLM. Warum soll ein zweites, kleineres Modell davor versuchen, Dinge zu „verstehen", wenn das eigentliche Modell dahinter das viel besser kann? Also Ollama komplett aus dem Workflow entfernt. Die Telegram-Nachricht geht jetzt direkt als Markdown-Datei in den Claude-Inbox-Ordner, ein systemd-Watcher pollt alle fünf Sekunden, Claude Code übernimmt, antwortet via Stop-Hook zurück an Telegram. Kein RAM-Problem, kein Memory-Error, und die Reaktionszeit ist spürbar schneller.

Beide Änderungen teilen eine Lektion: Komplexität ist kein Qualitätsmerkmal. Ein Layer, der Ressourcen frisst ohne Mehrwert zu bringen, muss raus – auch wenn er am Anfang schlau wirkte.

19. April 2026 Recht & Technik

Cookie-Banner: Brauche ich das überhaupt?

Jeder kennt sie, niemand mag sie: Cookie-Banner. Bevor ich blind einen einbaue, wollte ich erst mal prüfen, ob meine Seiten überhaupt Cookies setzen.

Also habe ich alle meine Projekte durchsucht – vita.eiskopani.de, das Whisky-Kuratorium und LernyTube. Das Ergebnis: Keines davon setzt Browser-Cookies. Was ich im Code gefunden habe, sind ausschließlich serverseitige Datenbank-Sessions (SQLAlchemy Session) – die haben mit Browser-Cookies nichts zu tun.

Kein Google Analytics, kein Tracking, keine Third-Party-Cookies. Das bedeutet: Ein Cookie-Banner wäre nicht nur unnötig, sondern sogar fragwürdig. Consent für etwas abfragen, das gar nicht stattfindet? Das verwirrt Besucher und ist rechtlich unsauber.

Die Lektion: Nicht jede „Best Practice" passt zu jedem Projekt. Erst prüfen, was technisch tatsächlich passiert – dann entscheiden. Falls ich später mal Login-Cookies oder Analytics einbaue, kommt der Banner dazu. Bis dahin bleibt er weg.

19. April 2026 Entwicklung

Mein Retro-Musik-Player spielt jetzt wirklich – und der Upload geht automatisch

Auf meiner Hobbys-Seite gibt es einen Retro-Player im Winamp-Stil mit 25 KI-generierten Songs. Das Problem: Die Songs waren nie wirklich auf dem Server – nur die Playlist war da, die Dateien fehlten. Heute habe ich das endlich gefixt.

Die Ursache war, dass meine Upload-Admin-Seite die Dateien nur lokal im Browser gespeichert hat (localStorage), aber nie auf den Server hochgeladen hat. Das habe ich komplett umgebaut: Jetzt gibt es einen Upload-Proxy auf meinem VPS, der die MP3-Dateien per SFTP direkt an den Hostinger-Webserver schickt. Drag & Drop in die Admin-Seite → Fortschrittsbalken → fertig auf dem Server. Löschen geht auch direkt über den Button.

Technisch ist das ein kleiner FastAPI-Service mit Paramiko (Python SFTP-Bibliothek), der hinter Traefik unter lernytube.eiskopani.de/music-api/ erreichbar ist. Die Authentifizierung nutzt denselben Passwort-Hash wie die Admin-Seite – keine doppelte Pflege.

Und weil „es funktioniert" nicht reicht, habe ich 14 Playwright-Tests geschrieben, die den Player automatisiert prüfen: Ist die Playlist da? Funktioniert Next/Prev? Kann man die Lautstärke ändern? Und vor allem: Sind alle 25 MP3-Dateien auf dem Server erreichbar (kein 404)? Alle Tests grün.

16. April 2026 Architektur

Monolith oder Microservices? Warum ich mich bewusst gegen den Hype entscheide

Microservices sind in aller Munde – jedes zweite Architektur-Diagramm auf LinkedIn sieht aus wie ein U-Bahn-Netzplan. Aber brauche ich das wirklich? Ich betreibe drei Projekte auf einem einzigen VPS mit begrenztem RAM. Heute habe ich mir die Frage ehrlich gestellt: Was passt zu meiner Situation – und was ist nur Cargo Cult?

Die Antwort war überraschend klar. Microservices lösen ein Teamproblem: Wenn fünf Teams gleichzeitig an einem Produkt arbeiten, braucht man unabhängige Deployments. Wenn ein Service 100-mal mehr Last bekommt als der Rest, will man ihn separat skalieren. Beides trifft auf mich nicht zu. Ich arbeite allein, meine Projekte haben überschaubare Last, und mein Server hat nicht mal genug RAM für Ollama ohne Swap.

Was Microservices kosten würden: mehr Container, mehr RAM-Verbrauch, Service Discovery, Health Checks, Retry-Logik, Distributed Tracing statt einfachem Logging. Jeder dieser Punkte ist ein eigenes Rabbit Hole – und keiner davon macht meine Schuh-Galerie oder mein Whisky-Kuratorium besser.

Mein Ansatz: Ein sauberer Monolith pro Projekt. Whisky-Kuratorium, LernyTube und EIS Schuh-Atelier sind bereits getrennte Repositories mit eigenen Containern – das ist die richtige Schnittlinie. Innerhalb jedes Projekts sorgen Router, Services und Models für Ordnung, ohne dass ich dafür Netzwerk-Calls zwischen Containern brauche.

Die wichtigste Erkenntnis: Architektur-Entscheidungen sollten von den eigenen Rahmenbedingungen ausgehen, nicht vom letzten Conference Talk. Ein Solo-Projekt auf einem VPS ist kein Netflix. Und wenn ein Projekt irgendwann wirklich wächst, kann ich Module immer noch extrahieren – aber dann aus einer funktionierenden Codebasis heraus, nicht aus einer vorzeitig zerlegten.

16. April 2026 Entwicklung

127 Tests und eine Pipeline – alle drei Projekte abgesichert

Heute war der Tag, an dem aus „es funktioniert auf meinem Server" ein echtes Sicherheitsnetz wurde. Für alle drei Projekte – LernyTube, Whisky-Kuratorium und EIS Schuh-Atelier – habe ich automatisierte Tests geschrieben: Unit-Tests, Integrationstests und End-to-End-Tests mit Playwright. Insgesamt 127 Stück.

Dazu kamen GitHub-Actions-Pipelines, die bei jedem Push automatisch loslaufen – mit echten Datenbanken als Service-Container, nicht mit Mocks. Denn genau da hatten wir vorher ein Problem: Mock-Tests bestanden, aber die echte Datenbank verhielt sich anders. Diese Lektion sitzt jetzt im Code statt nur im Kopf.

15. April 2026 Vita

Vom Zahlungsverkehr zur IT – mein Werdegang bekommt eine Seite

Heute ist der Lebenslauf auf meiner Vita-Seite live gegangen – nicht als trockene Auflistung, sondern als Timeline, die zeigt, wie sich mein Weg von der Sparkasse über die Deutsche Bahn bis in die IT-Welt entwickelt hat.

Was dabei sichtbar wird: Testmanagement und Release-Steuerung beim InGe-Tool, agiles Projektmanagement mit Scrum und SAFe, Prozessautomatisierung mit Power Apps und Power Automate, Stakeholder-Kommunikation quer durch den Konzern. Dazu kommen Seminare wie IREB, ITIL und Leading SAFe – und natürlich die laufende Weiterbildung zur Software Developerin (IHK) mit Python, SQL und Web-Entwicklung.

Besonders spannend finde ich, wie sich der rote Faden zieht: Egal ob Kreditvergabe digitalisieren, Formulare in Form.io bauen oder heute eigene Docker-Container auf dem VPS betreiben – es ging immer darum, Abläufe zu verstehen und dann besser zu machen.

14. April 2026 Projekt

LernyTube bekommt ein Zuhause – Admin-Panel, Forum und Kalender

Heute hat LernyTube einen großen Sprung gemacht: Aus der reinen Lern-App ist eine kleine Community-Plattform geworden. Ein komplett neues Admin-Panel ermöglicht die Verwaltung im Browser, und ein Forum mit Threads, Nachrichten und Emoji-Picker lädt zum Austausch ein.

Dazu kam ein Mini-Kalender auf dem Dashboard, der die eigenen Lernsessions tagesgenau anzeigt und filtert – so sieht man auf einen Blick, wann man wie viel gelernt hat. Über 900 neue Zeilen Code an einem Tag, verteilt auf 15 Dateien: Routen, Modelle, HTML-Templates und JavaScript. Es fühlt sich gut an, wenn aus einer Idee Schritt für Schritt ein echtes Produkt wird.

8. April 2026 Design

Old Money trifft Champagner-Gold – die Seite bekommt einen neuen Anstrich

Heute ging es nicht um neue Funktionen, sondern um Stil. Die ganze Seite hat einen einheitlichen Old-Money-Look bekommen: Karten im Blog-Stil – weiß, mit goldener Linie obenauf und einem zarten Schatten – ziehen jetzt durch alle Seiten. Projekte, Weiterbildung, KI-Experimente, alles wirkt wie aus einem Guss.

Im Header leuchtet ab sofort die aktuell besuchte Seite in Champagner-Gold mit einem weichen Glow und einer dunklen Patina-Linie darunter – wie ein Messingschild in einer alten Bibliothek. Die roten Trennlinien unter den Überschriften sind goldenen gewichen, alle Buttons tragen nun Kupfer-Gold mit Navy-Schrift, und das Motto-Band auf der Startseite hat das schreiende Rot gegen ein cremefarbenes Band mit goldenen Linien getauscht.

Drei Vorschläge habe ich Claude machen lassen, eine Test-Seite gebaut, im Browser verglichen, entschieden – und dann lief alles automatisch durch: CSS angepasst, Cache-Buster gebumpt, per SFTP deployt, in GitHub gesichert. Zum Abschluss noch das Portrait auf wer-bin-ich ausgetauscht. Manchmal ist ein guter Tag einfach ein Tag, an dem die Seite endlich so aussieht, wie sie sich anfühlen soll.

8. April 2026 KI & Automatisierung

„Mach weiter, ohne mich zu fragen" – ein Experiment

Heute habe ich Claude eine ungewöhnliche Anweisung gegeben: Mach weiter, auch wenn ich nicht antworte. Erledige alles, was du allein erledigen kannst. Schreib mir am Ende eine Liste, was wirklich nur ich entscheiden kann. So entstand eine Session, in der ich quasi nur zugeschaut habe.

Das Ergebnis: Sichere Passwörter generiert (64 Zeichen, kryptografisch zufällig), Datenbank mit den neuen Credentials neu aufgesetzt, ein zentrales Auth-Modul gebaut, alle Routen auf saubere Bearer-Token im Header umgestellt (statt Token in der URL), CORS auf die richtige Domain eingegrenzt, Passwort-Validierung serverseitig verschärft, der Excel-Upload auf 10 MB begrenzt – und am Ende ein Git-Push und ein neuer Blog-Eintrag.

Was übrig blieb: drei Punkte, die wirklich meine Entscheidung brauchen – ein DNS-Eintrag beim Provider, meine echte Admin-Email, und der erste visuelle Test im Browser. Genau die Art von Arbeitsteilung, die ich mir vorgestellt hatte: Die KI macht das Stumpfe und Mechanische, ich treffe die Entscheidungen, die nur ein Mensch treffen kann.

8. April 2026 Projekt

Vom Backend zum echten Erlebnis – das Kuratorium bekommt sein Gesicht

Heute ist das Whisky-Kuratorium von einer reinen API zu einer echten Anwendung gewachsen. Das komplette Frontend ist gebaut: eine Galerie mit Filtern nach Region, Kategorie und ABV, Detail-Ansichten zu jeder Flasche und ein Admin-Dashboard mit Tabs für Nutzerverwaltung, Excel-Import und das schnelle Hinzufügen einzelner Whiskys. Alles im Old-Money-Stil – Anthrazit, Gold, Playfair Display.

Im zweiten Teil des Tages ging es um Sicherheit: Sichere Passwörter generiert, CORS auf die Domain eingegrenzt, der Login-Mechanismus von URL-Parametern auf richtige Bearer-Token im Header umgestellt, Passwort-Validierung serverseitig verschärft. Aus einem Prototyp wird langsam ein produktionsreifes System.

6. April 2026 Projekt

Ein digitales Kuratorium für Whisky – von Null auf API

Heute ist ein neues Projekt geboren: das Whisky-Kuratorium. Die Idee? Eine exklusive, einladungsbasierte Plattform, auf der eine Whisky-Sammlung nicht nur katalogisiert, sondern mit Stil präsentiert wird. Dunkles Design, goldene Akzente – Old Money trifft auf moderne Technik.

In einer einzigen Session haben wir die komplette Infrastruktur aufgebaut: Docker-Container, PostgreSQL-Datenbank, Nutzer-System mit Einladungs-Hierarchie (man muss freigeschaltet werden), JWT-Authentifizierung und eine vollständige API für die Sammlung. Das Highlight: Ein Excel-Import, der eine ganze Sammlung per Drag-and-Drop einlesen kann – mit automatischer Erkennung, ob eine Flasche bereits existiert. Manchmal passiert an einem Tag mehr, als man für eine Woche plant.

4. April 2026 KI & Automatisierung

Von der Idee direkt in die Aufgabenliste – per Telegram

Heute stand ein ehrgeiziges Ziel auf dem Plan: Aufgaben per Telegram-Nachricht an Claude Code übergeben – vollautomatisch, ohne Umweg. Was simpel klingt, entpuppte sich als Detektivarbeit durch SSL-Zertifikate, N8N-Interna und Docker-Berechtigungen.

Das Ergebnis: Ein funktionierender Workflow, der eine Nachricht wie „Baue einen Logout-Button" entgegennimmt, per lokalem KI-Modell (Ollama) in eine strukturierte Entwicklungsaufgabe verwandelt und in eine Warteschlange schreibt. Neu dazu kam ein /status-Befehl, der auf Knopfdruck zeigt, welche Aufgaben offen und erledigt sind. Kleine Nachricht, große Wirkung.

30. März 2026 KI & Automatisierung

Ordnung im Chaos – ein System das mitdenkt

Heute haben wir etwas gebaut, das man nicht sieht – aber das jede zukünftige Arbeitssession einfacher macht. Ein Session-Management-System für meine KI-Zusammenarbeit: eine Start-Datei, die Claude beim Öffnen sofort weiß, welche Projekte laufen und wo er weitermachen soll.

Und eine Ende-Datei, die sicherstellt, dass am Schluss nichts verloren geht. Die echte Herausforderung? Alle laufenden Projekte, Zugangsdaten, Infrastrukturdetails und Arbeitsregeln so zu strukturieren, dass eine KI in Sekunden einsatzbereit ist – ohne dass ich jedes Mal von vorne erklären muss. Das ist wie ein perfektes Briefing für einen neuen Kollegen, den man immer wieder frisch begrüßt.

30. März 2026 Entwicklung

Mein Blog geht live – und der Header wächst

Heute habe ich meiner vita-Website zwei neue Navigationspunkte gegeben: Blog und Gästebuch. Klingt klein – aber dahinter steckt mehr als ein paar Links.

Es ist der Entschluss, meinen Lernweg öffentlich zu machen. Nicht als Hochglanz-Portfolio, sondern als echtes Tagebuch meiner Entwicklung.

Dieser Blog wird von mir und meinem KI-Assistenten Claude gepflegt. Nach jeder Arbeits-Session entsteht hier ein Eintrag – damit nichts verloren geht und du nachvollziehen kannst, wie Projekte wirklich entstehen.