
La pagina di login È la demo
GeekBye v1.7.5 ha aggiunto uno screenshot del prodotto alla pagina di login e l'ha cancellato lo stesso giorno — ricostruendolo come componenti reali. E poi: l'utente che è stato più veloce dell'OCR, e come sono davvero 25 commit di stile in un solo giorno.
GeekBye v1.7.5 è una release da una settimana con doppia personalità: 37 commit, di cui 28 sono un redesign della pagina di login — e 25 di quelli sono micro-ritocchi style(login), tutti atterrati in un solo giorno. È anche la release che ha sistemato una delle race più istruttive della codebase. Entrambe le storie meritano di essere raccontate, e si incontrano nella stessa idea: la pagina di login è la prima cosa che vede un utente non autenticato, quindi è meglio che sia il prodotto, non una foto del prodotto.
Uno screenshot, per circa cinque ore
Il redesign è iniziato in modo convenzionale. Ristrutturare su due colonne, mettere l'accesso a sinistra e mostrare il prodotto a destra — come immagine. I commit di tarda mattinata fanno esattamente questo: alle 11:57 un vero screenshot di anteprima atterra nel repo, un PNG da 114 KB, aggiornato una volta sei minuti dopo.
Alle 17:04 era sparito. Il commit della svolta sostituisce l'immagine statica con 344 righe di componenti reali — un pannello LoginDemo assemblato da otto piccoli pezzi che replicano la vera UI dell'overlay: la pillola di navigazione della registrazione con le sue barre EQ pulsanti e il pulsante di stop, il pannello di chat con le tab Chat/Transcript, una risposta dell'assistente renderizzata (che spiega lo useEffect di React, guarda caso), le azioni rapide "Tell me more / Simplify / Show example" (dimmi di più / semplifica / mostra un esempio), la riga dei prompt live e il campo Assist con ⌘⏎.
Siamo precisi sulla parola «demo», perché è facile esagerare: i pulsanti hanno stati hover reali — bagliori, shimmer, transizioni — ma niente è collegato al clic, e il campo di input è in sola lettura. Non è una sandbox. Quello che è, è il vero vocabolario UI del prodotto renderizzato dal vivo: lo stesso asset del logo, lo stesso trattamento a bordo sfumato e backdrop-blur, lo stesso import di productName che usa il sistema white-label — così la demo si ribrandizza automaticamente per ogni prodotto costruito da questa codebase. Uno screenshot non può fare niente di tutto questo. Uno screenshot è vecchio il giorno in cui lo scatti, sfocato sul display sbagliato e marchiato per sempre con il prodotto che ti è capitato di catturare. I componenti sono nitidi a qualsiasi DPI, sempre aggiornati e corretti per ogni brand — perché non sono una foto del design system, sono il design system.
Il PNG cancellato, per inciso, è ancora nel repo al tag della release — orfano, referenziato da niente. Ogni codebase si porta dietro qualche fossile dell'approccio che ha perso.
Come sono 25 commit di stile in un giorno
Il log dei commit di quel singolo giorno è il taccuino di schizzi di un designer, conservato con un'onestà insolita. Il rapporto tra le colonne è passato a 40/60, poi 45/55. Un'etichetta "Works with" (funziona con) sopra i loghi delle piattaforme è stata aggiunta a mezzogiorno, riposizionata e rimossa — è vissuta circa mezza giornata. La fila stessa dei loghi delle piattaforme (Google Meet, Teams, Zoom, Slack, Webex), aggiunta alle 10:59 di mattina, è stata cancellata per intero alle 22:08 di quella sera. E il footer ha richiesto una saga a quattro approcci per allinearsi: un singolo container wrapper, poi la rimozione delle classi di centratura, poi la centratura con flexbox, poi semplicemente spingerlo un po' più vicino al fondo.
Sarebbe facile leggerla come churn. Noi la leggiamo come la forma reale del lavoro di design: si converge renderizzando, guardando e aggiustando — e farlo in 25 piccoli commit invece che in un unico "redesign login page" schiacciato significa che la ricerca stessa è registrata. Quando qualcuno chiede «non avevamo provato una fila di loghi, una volta?», la risposta è nella cronologia, con i timestamp.
L'utente che è stato più veloce dell'OCR
La storia di ingegneria della release è avvenuta cinque giorni prima, in una catena di fix da tre commit. Dalla v1.5.12, premere Cmd+H accoda uno screenshot con feedback istantaneo: la miniatura compare subito nella coda, e l'estrazione del testo — OCR locale con Apple Vision, all'incirca da uno a due secondi — gira in background. L'evento di accodamento parte letteralmente con ocrText: '' e un commento che promette che si riempirà più tardi.
È una buona ottimizzazione, e ha coniato una race. Un utente veloce preme Cmd+H e invia subito la sua domanda. Il campo di testo dello screenshot è ancora vuoto. La richiesta parte senza contenuto dello schermo, e il modello risponde — con verità, in modo esasperante — "I cannot see images" (non posso vedere immagini). Il percorso ingenuo non ha fallito con un errore; ha fallito con una risposta corretta alla domanda sbagliata, che è il modo più confondente in cui il software può fallire.
Il fix blocca il percorso di invio sul lavoro asincrono che l'ottimizzazione aveva rimandato: se un qualsiasi screenshot in coda ha ancora il testo OCR vuoto, la richiesta si parcheggia e la UI mostra un indicatore "Reading screen..." (sto leggendo lo schermo); uno useEffect scatta nel momento in cui il testo arriva e invia la richiesta con il contenuto estratto completo. Due dettagli specifici di React nel diff meritano di essere rubati: la coda degli screenshot viene specchiata in una ref sincronizzata durante il render, perché la catena di closure dei gestori di eventi catturava stato vecchio; e la richiesta parcheggiata viene inviata direttamente invece che tramite l'hook generico delle richieste in coda, per lo stesso motivo di stale closure.
E c'è una piega onesta registrata proprio nel messaggio di commit: i log di tracing aggiunti per dare la caccia a questa race hanno rivelato un secondo bug sul backend — l'assemblaggio del prompt scartava del tutto il testo dello screenshot in uno dei percorsi di codice. Un sintomo, due bug, trovati strumentando l'intera catena e guardando dove il testo spariva. La catena si è chiusa con una decisione di prodotto, nove minuti dopo il fix della race: Cmd+H accoda gli screenshot per l'analisi in batch, mentre Cmd+Enter scatta sempre una cattura fresca dello schermo corrente — due flussi di lavoro distinti invece di uno ambiguo. (Cosa fa davvero l'Assist di Cmd+Enter è un post a sé: aiuto IA istantaneo su qualsiasi cosa tu stia guardando.)
Una piccola coda dalla stessa settimana, per i lettori del capitolo white-label: lo User-Agent Product/version (platform) ha ricevuto un fix per la modalità dev, perché app.getVersion() in un Electron non pacchettizzato restituisce la versione di Electron, non quella del prodotto. Le stringhe di identità, come sempre, trapelano dalle tubature.
Tre cose che questa release ci ha insegnato
- Renderizza il prodotto, non fotografarlo. Una demo della pagina di login costruita con componenti reali si ribrandizza da sola, sopravvive a qualsiasi densità di display e non può invecchiare. L'approccio dello screenshot è stato provato e cancellato nell'arco di una giornata lavorativa — esperimento economico, verdetto chiaro.
- Ogni ottimizzazione asincrona ha bisogno di un blocco nel punto d'uso. «Feedback istantaneo con testo OCR vuoto» era la scelta UX giusta, ma il percorso di invio ha dovuto imparare ad aspettare quello che l'ottimizzazione aveva rimandato. Se rimandi del lavoro, trova ogni consumatore del suo risultato e insegnagli la differenza tra «vuoto» e «non ancora pronto».
- Strumenta la catena, non il sospettato. I log di tracing hanno seguito il testo dello screenshot da un capo all'altro — dal gestore della scorciatoia all'IPC al client API — ed è per questo che una sola indagine ha chiuso due bug, uno dei quali dall'altra parte della rete.
Per il capitolo precedente della storia v1, riunioni che finalmente ritrovi (v1.7.3); e per tutto l'arco, l'anatomia del pubblicare software fino alla perfezione.