Steven
Steven6 min läsning

Inloggningssidan ÄR demot

GeekBye v1.7.5 la till en produktskärmdump på inloggningssidan och raderade den samma dag — och byggde om den som riktiga komponenter i stället. Dessutom: användaren som var snabbare än OCR:en, och hur 25 style-commits på en dag faktiskt ser ut.

Utveckling
Design
UX
GeekBye-releaser
Inloggningssidan ÄR demot

GeekBye v1.7.5 är en enveckasrelease med kluven personlighet: 37 commits, varav 28 är en omgjord inloggningssida — och 25 av dem är style(login)-mikrojusteringar, alla landade på en och samma dag. Det är också releasen som fixade ett av de mest lärorika racen i kodbasen. Båda historierna är värda att berätta, och de möts i samma idé: inloggningssidan är det första en oautentiserad användare ser, så det är bäst att den är produkten, inte en bild av den.

En skärmdump, i ungefär fem timmar

Omdesignen började konventionellt. Strukturera om till två kolumner, lägg inloggningen till vänster och visa produkten till höger — som en bild. Commits på sena förmiddagen gör exakt det: klockan 11:57 landar en riktig förhandsvisningsskärmdump i repot, en PNG på 114 KB, och uppdateras en gång sex minuter senare.

Klockan 17:04 var den borta. Pivot-committen ersätter den statiska bilden med 344 rader riktiga komponenter — en LoginDemo-panel hopsatt av åtta små bitar som replikerar det faktiska overlay-UI:t: inspelningens navpiller med sina pulserande EQ-staplar och stoppknapp, chattpanelen med Chat/Transcript-flikar, ett renderat assistentsvar (som passande nog förklarar Reacts useEffect), snabbåtgärderna "Tell me more / Simplify / Show example", live-prompt-raden och ⌘⏎ Assist-inmatningen.

Låt oss vara precisa med ordet "demo", för det är lätt att överlova: knapparna har riktiga hover-states — glöd, skimmer, övergångar — men inget är kopplat till klick, och inmatningsfältet är skrivskyddat. Det är ingen sandlåda. Vad det är, är produktens faktiska UI-vokabulär renderat live: samma logotypfil, samma gradient-border- och backdrop-blur-behandling, samma productName-import som white-label-systemet använder — så demot ombrandas automatiskt för varje produkt som byggs från den här kodbasen. En skärmdump klarar inget av det. En skärmdump är inaktuell samma dag du tar den, suddig på fel skärm och permanent brandad som den produkt du råkade fånga. Komponenter är skarpa i alla DPI, alltid aktuella och korrekta för varje varumärke — för de är inte en bild av designsystemet, de är designsystemet.

Den raderade PNG:n ligger för övrigt kvar i repot vid release-taggen — föräldralös, refererad av ingenting. Varje kodbas bär på några fossil av angreppssättet som förlorade.

Hur 25 style-commits på en dag ser ut

Commit-loggen från den enda dagen är en designers skissbok, bevarad med ovanlig ärlighet. Kolumnförhållandet gick 40/60, sedan 45/55. En "Works with"-etikett (fungerar med) ovanför plattformslogotyperna lades till mitt på dagen, flyttades och togs bort — den levde ungefär ett halvt dygn. Själva plattformslogoraden (Google Meet, Teams, Zoom, Slack, Webex), tillagd 10:59 på förmiddagen, raderades helt 22:08 samma kväll. Och footern krävde en saga i fyra angreppssätt för att bli rätt: en enda wrapper-container, sedan borttagning av centreringsklasserna, sedan flexbox-centrering, sedan att bara knuffa den närmare botten.

Det vore lätt att läsa som spinn. Vi läser det som designarbetets faktiska form: du konvergerar genom att rendera, titta och justera — och att göra det i 25 små commits i stället för en squashad "redesign login page" betyder att själva sökandet är dokumenterat. När någon frågar "provade vi inte en logorad en gång?" finns svaret i historiken, med tidsstämplar.

Användaren som var snabbare än OCR:en

Releasens engineering-historia hände fem dagar tidigare, i en fixkedja på tre commits. Sedan v1.5.12 köar Cmd+H en skärmdump med omedelbar feedback: miniatyren dyker upp i kön direkt, och textextraheringen — lokal Apple Vision-OCR, ungefär ~1-2 sekunder — körs i bakgrunden. Kö-eventet skeppas bokstavligen med ocrText: '' och en kommentar som lovar att den fylls i senare.

Det är en bra optimering, och den myntade ett race. En snabb användare trycker Cmd+H och skickar sin fråga direkt. Skärmdumpens textfält är fortfarande tomt. Requesten går ut utan skärminnehåll, och modellen svarar — sanningsenligt, rasande nog — "I cannot see images" (jag kan inte se bilder). Den naiva vägen fallerade inte med ett fel; den fallerade med ett korrekt svar på fel fråga, vilket är det mest förvirrande sätt mjukvara kan fallera på.

Fixen spärrar skicka-vägen på async-arbetet som optimeringen sköt upp: om någon köad skärmdump fortfarande har tom OCR-text parkeras requesten och UI:t visar en "Reading screen..."-indikator (läser skärmen); en useEffect triggar i samma ögonblick texten landar och skickar requesten med hela det extraherade innehållet. Två React-specifika detaljer i diffen är värda att sno: skärmdumpskön speglas in i en ref som synkas under render, eftersom event-hanterarnas closure-kedja fångade inaktuellt state; och den parkerade requesten skickas direkt i stället för genom den generiska queued-request-hooken, av samma stale-closure-skäl.

Och det finns en ärlig krök dokumenterad direkt i commit-meddelandet: spårningsloggarna som lades till för att jaga det här racet avslöjade en andra bugg på backend — prompt-sammansättningen tappade skärmdumpstexten helt i en kodväg. Ett symtom, två buggar, hittade genom att instrumentera hela kedjan och titta på var texten försvann. Kedjan slutade med ett produktbeslut, nio minuter efter race-fixen: Cmd+H köar skärmdumpar för batchanalys, medan Cmd+Enter alltid tar en färsk bild av den aktuella skärmen — två distinkta arbetsflöden i stället för ett tvetydigt. (Vad Cmd+Enters Assist faktiskt gör är ett eget inlägg: omedelbar AI-hjälp med vad du än tittar på.)

En liten koda från samma vecka, för läsare av white-label-kapitlet: Product/version (platform)-User-Agenten fick en dev-läges-fix, eftersom app.getVersion() i opaketerad Electron returnerar Electrons version, inte produktens. Identitetssträngar läcker, som alltid, i rörläggningen.

Tre saker den här releasen lärde oss

  1. Rendera produkten, fotografera den inte. Ett inloggningssidedemo byggt av riktiga komponenter auto-ombrandas, överlever varje skärmtäthet och kan inte drifta ur datum. Skärmdumpsansatsen provades och raderades inom en arbetsdag — billigt experiment, tydlig dom.
  2. Varje async-optimering behöver en spärr vid användningspunkten. "Omedelbar feedback med tom OCR-text" var rätt UX-beslut, men skicka-vägen var tvungen att lära sig vänta på det optimeringen sköt upp. Om du skjuter upp arbete, hitta varje konsument av dess resultat och lär den skillnaden mellan "tomt" och "inte klart än".
  3. Instrumentera kedjan, inte den misstänkte. Spårningsloggarna följde skärmdumpstexten från ände till ände — kortkommandohanterare till IPC till API-klient — och det är därför en utredning stängde två buggar, varav en på andra sidan nätverket.

För det föregående kapitlet i v1-historien, möten du faktiskt hittar igen (v1.7.3); och för hela bågen, anatomin i att skeppa mjukvara till perfektion.