
Die Login-Seite IST die Demo
GeekBye v1.7.5 fügte der Login-Seite einen Produkt-Screenshot hinzu und löschte ihn noch am selben Tag — um ihn stattdessen aus echten Komponenten neu zu bauen. Außerdem: der Nutzer, der schneller war als die OCR, und wie 25 Style-Commits an einem Tag wirklich aussehen.
GeekBye v1.7.5 ist ein Ein-Wochen-Release mit gespaltener Persönlichkeit: 37 Commits, davon 28 ein Redesign der Login-Seite — und 25 davon sind style(login)-Mikro-Anpassungen, alle an einem einzigen Tag gelandet. Es ist auch das Release, das eines der lehrreichsten Races der Codebasis behoben hat. Beide Geschichten sind es wert, erzählt zu werden, und sie treffen sich in derselben Idee: die Login-Seite ist das Erste, was ein nicht angemeldeter Nutzer sieht — also sollte sie besser das Produkt sein, nicht ein Bild davon.
Ein Screenshot, für ungefähr fünf Stunden
Das Redesign begann konventionell. Umbau auf zwei Spalten, die Anmeldung links, das Produkt rechts — als Bild. Die Commits am späten Vormittag tun genau das: um 11:57 landet ein echter Vorschau-Screenshot im Repo, ein 114 KB großes PNG, das sechs Minuten später einmal aktualisiert wird.
Um 17:04 war es weg. Der Pivot-Commit ersetzt das statische Bild durch 344 Zeilen echte Komponenten — ein LoginDemo-Panel, zusammengesetzt aus acht kleinen Teilen, die die echte Overlay-UI nachbilden: die Aufnahme-Navigationspille mit ihren pulsierenden EQ-Balken und dem Stopp-Button, das Chat-Panel mit Chat/Transcript-Tabs, eine gerenderte Assistenten-Antwort (die passenderweise Reacts useEffect erklärt), die Schnellaktionen "Tell me more / Simplify / Show example" (mehr erzählen / vereinfachen / Beispiel zeigen), die Live-Prompt-Zeile und das ⌘⏎-Assist-Eingabefeld.
Seien wir präzise beim Wort „Demo", denn es ist leicht, zu viel zu behaupten: die Buttons haben echte Hover-States — Glows, Schimmer, Transitions — aber nichts ist an Klicks angeschlossen, und das Eingabefeld ist schreibgeschützt. Es ist kein Sandkasten. Was es ist: das echte UI-Vokabular des Produkts, live gerendert — dasselbe Logo-Asset, dieselbe Behandlung aus Gradient-Border und Backdrop-Blur, derselbe productName-Import, den das White-Label-System nutzt — sodass sich die Demo für jedes aus dieser Codebasis gebaute Produkt automatisch umbrandet. Ein Screenshot kann nichts davon. Ein Screenshot ist am Tag der Aufnahme veraltet, auf dem falschen Display unscharf und für immer mit dem Produkt gebrandet, das man zufällig aufgenommen hat. Komponenten sind bei jedem DPI scharf, immer aktuell und für jede Marke korrekt — weil sie kein Bild des Designsystems sind, sondern das Designsystem sind.
Das gelöschte PNG liegt übrigens am Release-Tag immer noch im Repo — verwaist, von nichts referenziert. Jede Codebasis trägt ein paar Fossilien des Ansatzes mit sich, der verloren hat.
Wie 25 Style-Commits an einem Tag aussehen
Das Commit-Log dieses einen Tages ist das Skizzenbuch eines Designers, mit ungewöhnlicher Ehrlichkeit aufbewahrt. Das Spaltenverhältnis ging auf 40/60, dann 45/55. Ein „Works with"-Label (funktioniert mit) über den Plattform-Logos wurde mittags hinzugefügt, umpositioniert und entfernt — es lebte etwa einen halben Tag. Die Plattform-Logo-Reihe selbst (Google Meet, Teams, Zoom, Slack, Webex), um 10:59 morgens hinzugefügt, wurde um 22:08 am selben Abend komplett gelöscht. Und der Footer brauchte eine Saga aus vier Ansätzen, um sich auszurichten: ein einzelner Wrapper-Container, dann das Entfernen der Zentrier-Klassen, dann Flexbox-Zentrierung, dann ihn einfach näher an den unteren Rand schieben.
Man könnte das leicht als Churn lesen. Wir lesen es als die tatsächliche Gestalt von Designarbeit: man konvergiert durch Rendern, Hinschauen und Nachjustieren — und das in 25 kleinen Commits statt in einem gequetschten „redesign login page" zu tun heißt, dass die Suche selbst protokolliert ist. Wenn jemand fragt „hatten wir nicht mal eine Logo-Reihe probiert?", steht die Antwort in der Historie, mit Timestamps.
Der Nutzer, der schneller war als die OCR
Die Engineering-Geschichte des Release passierte fünf Tage früher, in einer Fix-Kette aus drei Commits. Seit v1.5.12 reiht Cmd+H einen Screenshot mit sofortigem Feedback in die Queue ein: das Thumbnail erscheint sofort in der Warteschlange, und die Textextraktion — lokale Apple-Vision-OCR, grob ein bis zwei Sekunden — läuft im Hintergrund. Das Queue-Event geht buchstäblich mit ocrText: '' raus, samt Kommentar mit dem Versprechen, dass es sich später füllt.
Das ist eine gute Optimierung, und sie prägte ein Race. Ein schneller Nutzer drückt Cmd+H und sendet sofort seine Frage ab. Das Textfeld des Screenshots ist noch leer. Der Request geht ohne Bildschirminhalt raus, und das Modell antwortet — wahrheitsgemäß, zum Verzweifeln — "I cannot see images" (ich kann keine Bilder sehen). Der naive Pfad scheiterte nicht mit einem Fehler; er scheiterte mit einer korrekten Antwort auf die falsche Frage — die verwirrendste Art, auf die Software scheitern kann.
Der Fix sperrt den Sende-Pfad auf die asynchrone Arbeit, die die Optimierung aufgeschoben hatte: hat irgendein Screenshot in der Queue noch leeren OCR-Text, wird der Request geparkt und die UI zeigt einen „Reading screen..."-Indikator (Bildschirm wird gelesen); ein useEffect feuert in dem Moment, in dem der Text eintrifft, und schickt den Request mit dem vollständig extrahierten Inhalt los. Zwei React-spezifische Details im Diff lohnen das Stehlen: die Screenshot-Queue wird in eine Ref gespiegelt, die während des Renderns synchronisiert wird, weil die Closure-Kette der Event-Handler veralteten State einfing; und der geparkte Request wird direkt gesendet statt über den generischen Queued-Request-Hook — aus demselben Stale-Closure-Grund.
Und direkt in der Commit-Message steckt eine ehrliche Falte: die Tracing-Logs, die zur Jagd auf dieses Race eingebaut wurden, enthüllten einen zweiten Bug im Backend — die Prompt-Assembly ließ den Screenshot-Text in einem Codepfad komplett unter den Tisch fallen. Ein Symptom, zwei Bugs — gefunden, indem man die ganze Kette instrumentierte und zusah, wo der Text verschwand. Die Kette endete mit einer Produktentscheidung, neun Minuten nach dem Race-Fix: Cmd+H reiht Screenshots für die Batch-Analyse in die Queue ein, während Cmd+Enter immer eine frische Aufnahme des aktuellen Bildschirms macht — zwei klar getrennte Workflows statt eines mehrdeutigen. (Was der Assist von Cmd+Enter tatsächlich tut, ist ein eigener Beitrag: sofortige KI-Hilfe zu dem, was man gerade ansieht.)
Eine kleine Coda aus derselben Woche, für Leser des White-Label-Kapitels: der Product/version (platform)-User-Agent bekam einen Dev-Mode-Fix, weil app.getVersion() in unverpacktem Electron Electrons Version zurückgibt, nicht die des Produkts. Identitäts-Strings lecken, wie immer, in der Verrohrung.
Drei Dinge, die uns dieses Release lehrte
- Rendere das Produkt, fotografiere es nicht. Eine Login-Seiten-Demo aus echten Komponenten brandet sich automatisch um, überlebt jede Display-Dichte und kann nicht veralten. Der Screenshot-Ansatz wurde innerhalb eines Arbeitstages ausprobiert und gelöscht — billiges Experiment, klares Urteil.
- Jede asynchrone Optimierung braucht eine Sperre am Nutzungspunkt. „Sofortiges Feedback mit leerem OCR-Text" war die richtige UX-Entscheidung, aber der Sende-Pfad musste lernen, auf das zu warten, was die Optimierung aufgeschoben hatte. Wenn du Arbeit aufschiebst, finde jeden Konsumenten ihres Ergebnisses und bring ihm den Unterschied zwischen „leer" und „noch nicht fertig" bei.
- Instrumentiere die Kette, nicht den Verdächtigen. Die Tracing-Logs folgten dem Screenshot-Text von Ende zu Ende — vom Shortcut-Handler über IPC bis zum API-Client — und genau deshalb schloss eine Untersuchung zwei Bugs, einen davon auf der anderen Seite des Netzwerks.
Für das vorige Kapitel der v1-Geschichte, Meetings, die man endlich wiederfindet (v1.7.3); und für den ganzen Bogen, die Anatomie, Software bis zur Perfektion auszuliefern.