
A página de login É a demo
GeekBye v1.7.5 adicionou uma captura de tela do produto à página de login e a apagou no mesmo dia — reconstruindo-a como componentes reais. E mais: o usuário que foi mais rápido que o OCR, e como são de verdade 25 commits de estilo em um único dia.
GeekBye v1.7.5 é um lançamento de uma semana com dupla personalidade: 37 commits, dos quais 28 são um redesign da página de login — e 25 desses são micro-ajustes style(login), todos aterrissados em um único dia. É também o lançamento que corrigiu uma das corridas mais instrutivas da base de código. As duas histórias merecem ser contadas, e elas se encontram na mesma ideia: a página de login é a primeira coisa que um usuário não autenticado vê, então é melhor que ela seja o produto, não uma foto dele.
Uma captura de tela, por umas cinco horas
O redesign começou de forma convencional. Reestruturar em duas colunas, colocar o login à esquerda e mostrar o produto à direita — como imagem. Os commits do fim da manhã fazem exatamente isso: às 11:57 uma captura de preview real aterrissa no repositório, um PNG de 114 KB, atualizado uma vez seis minutos depois.
Às 17:04 ela tinha sumido. O commit da virada substitui a imagem estática por 344 linhas de componentes reais — um painel LoginDemo montado a partir de oito peças pequenas que replicam a UI real do overlay: a pílula de navegação da gravação com suas barras de EQ pulsantes e o botão de stop, o painel de chat com abas Chat/Transcript, uma resposta do assistente renderizada (explicando o useEffect do React, apropriadamente), as ações rápidas "Tell me more / Simplify / Show example" (conte mais / simplifique / mostre um exemplo), a fileira de prompts ao vivo e o input do Assist com ⌘⏎.
Vamos ser precisos com a palavra "demo", porque é fácil prometer demais: os botões têm estados de hover reais — brilhos, shimmers, transições — mas nada está ligado ao clique, e o input é somente leitura. Não é um sandbox. O que ela é, é o vocabulário de UI real do produto renderizado ao vivo: o mesmo asset de logo, o mesmo tratamento de borda em degradê e backdrop-blur, o mesmo import de productName que o sistema white-label usa — de modo que a demo se rebrandeia automaticamente para cada produto construído a partir desta base de código. Uma captura de tela não faz nada disso. Uma captura fica desatualizada no dia em que você a tira, borrada na tela errada e marcada para sempre com o produto que você por acaso capturou. Componentes ficam nítidos em qualquer DPI, sempre atuais e corretos para cada marca — porque eles não são uma foto do design system, eles são o design system.
O PNG apagado, aliás, ainda está no repositório na tag do lançamento — órfão, referenciado por nada. Toda base de código carrega alguns fósseis da abordagem que perdeu.
Como são 25 commits de estilo em um dia
O log de commits daquele único dia é o caderno de rascunhos de um designer, preservado com uma honestidade incomum. A proporção das colunas foi 40/60, depois 45/55. Um rótulo "Works with" (funciona com) acima dos logos de plataformas foi adicionado ao meio-dia, reposicionado e removido — viveu mais ou menos meio dia. A própria fileira de logos de plataformas (Google Meet, Teams, Zoom, Slack, Webex), adicionada às 10:59 da manhã, foi apagada inteira às 22:08 daquela noite. E o footer levou uma saga de quatro abordagens para alinhar: um único container wrapper, depois remover as classes de centralização, depois centralizar com flexbox, depois só empurrá-lo um pouco mais para perto da parte de baixo.
Seria fácil ler isso como churn. Nós lemos como o formato real do trabalho de design: você converge renderizando, olhando e ajustando — e fazer isso em 25 commits pequenos em vez de um único "redesign login page" espremido significa que a própria busca fica registrada. Quando alguém perguntar "a gente não tentou uma fileira de logos uma vez?", a resposta está no histórico, com timestamps.
O usuário que foi mais rápido que o OCR
A história de engenharia do lançamento aconteceu cinco dias antes, numa cadeia de correção de três commits. Desde a v1.5.12, apertar Cmd+H enfileira uma captura com feedback instantâneo: a miniatura aparece na fila imediatamente, e a extração de texto — OCR local com Apple Vision, de um a dois segundos mais ou menos — roda em segundo plano. O evento de enfileiramento sai literalmente com ocrText: '' e um comentário prometendo que será preenchido depois.
É uma boa otimização, e ela cunhou uma corrida. Um usuário rápido aperta Cmd+H e envia a pergunta imediatamente. O campo de texto da captura ainda está vazio. A requisição sai sem conteúdo de tela, e o modelo responde — com verdade, de forma exasperante — "I cannot see images" (não consigo ver imagens). O caminho ingênuo não falhou com um erro; falhou com uma resposta correta à pergunta errada, que é o jeito mais confuso de um software falhar.
A correção trava o caminho de envio sobre o trabalho assíncrono que a otimização adiou: se alguma captura enfileirada ainda tem o texto de OCR vazio, a requisição fica estacionada e a UI mostra um indicador "Reading screen..." (lendo a tela); um useEffect dispara no momento em que o texto chega e envia a requisição com o conteúdo extraído completo. Dois detalhes específicos de React no diff valem a pena roubar: a fila de capturas é espelhada em uma ref sincronizada durante o render, porque a cadeia de closures do manipulador de eventos estava capturando estado obsoleto; e a requisição estacionada é enviada diretamente em vez de passar pelo hook genérico de requisições enfileiradas, pelo mesmo motivo de stale closure.
E há uma dobra honesta registrada na própria mensagem de commit: os logs de rastreamento adicionados para caçar essa corrida revelaram um segundo bug no backend — a montagem do prompt estava descartando o texto da captura por completo em um dos caminhos de código. Um sintoma, dois bugs, encontrados instrumentando a cadeia inteira e observando onde o texto desaparecia. A cadeia terminou com uma decisão de produto, nove minutos depois da correção da corrida: Cmd+H enfileira capturas para análise em lote, enquanto Cmd+Enter sempre tira uma captura fresca da tela atual — dois fluxos de trabalho distintos em vez de um ambíguo. (O que o Assist do Cmd+Enter faz de verdade é um post à parte: ajuda de IA instantânea sobre o que você estiver olhando.)
Uma pequena coda da mesma semana, para os leitores do capítulo de white-label: o User-Agent Product/version (platform) ganhou uma correção para o modo dev, porque app.getVersion() no Electron não empacotado retorna a versão do Electron, não a do produto. Strings de identidade, como sempre, vazam pelo encanamento.
Três coisas que este lançamento nos ensinou
- Renderize o produto, não o fotografe. Uma demo de página de login construída com componentes reais se rebrandeia sozinha, sobrevive a qualquer densidade de tela e não consegue ficar desatualizada. A abordagem da captura de tela foi testada e apagada dentro de um dia de trabalho — experimento barato, veredito claro.
- Toda otimização assíncrona precisa de uma trava no ponto de uso. "Feedback instantâneo com texto de OCR vazio" era a decisão de UX certa, mas o caminho de envio precisou aprender a esperar pelo que a otimização adiou. Se você adia trabalho, encontre cada consumidor do resultado dele e ensine-o a diferença entre "vazio" e "ainda não pronto".
- Instrumente a cadeia, não o suspeito. Os logs de rastreamento seguiram o texto da captura de ponta a ponta — do manipulador do atalho ao IPC ao cliente de API — e é por isso que uma investigação fechou dois bugs, um deles do outro lado da rede.
Para o capítulo anterior da história v1, reuniões que você finalmente encontra de novo (v1.7.3); e para todo o arco, a anatomia de entregar software até a perfeição.