Skip to content

JHONATAN OLIVEIRA®

PORTFOLIO / 2026

FRONTEND / PRODUCT / DESIGN

Engineering, direction and digital craft in one continuous system.

ISSUE / 01

Back to journal

04 / Journal

Technology / Oct 2026

Uma bolinha verde pode ser um problema de arquitetura

O que construir presença no PING me ensinou sobre sincronização, múltiplos dispositivos e a diferença entre mostrar um status e representar a realidade.

Published

October 26, 2026

READ TIME

5 min read

#PING#presença em tempo real#arquitetura#Electron#UX

Quando desenhamos uma lista de amigos, a presença costuma parecer uma das funcionalidades mais simples do produto.

Uma bolinha verde para quem está online. Cinza para quem saiu. Talvez amarelo para ausente. O componente cabe em poucas linhas; o requisito, não.

No PING, essa pequena informação virou uma das melhores maneiras de entender como um detalhe visual pode atravessar toda a arquitetura. Porque a bolinha não está dizendo apenas que um servidor recebeu um evento. Ela está fazendo uma promessa: há uma pessoa disponível do outro lado.

Quando essa promessa falha, a experiência começa a perder confiança.

“Online” é uma decisão de produto antes de ser uma condição técnica

Uma aba aberta é suficiente para considerar alguém online? E se o computador estiver bloqueado? E se houver uma chamada ativa em segundo plano? E quando a pessoa escolhe aparecer offline?

Essas perguntas não se resolvem com um isOnline: true no banco. Precisam de semântica.

No PING, existem estados como online, ausente, ocupado e offline. Cada um comunica uma expectativa diferente. Mas a disponibilidade exibida também pode depender do dispositivo, da sessão e da escolha deliberada da pessoa.

Por isso é importante separar pelo menos três ideias: conectividade, atividade e visibilidade. Alguém pode estar conectado e inativo. Pode estar ativo em uma chamada, mesmo sem interagir com a janela. E pode estar conectado, mas preferir não ser exibido como disponível.

Misturar essas dimensões produz bugs que parecem aleatórios, embora tenham origem numa modelagem confusa.

O tempo real não elimina o tempo

Em aplicações distribuídas, “agora” não é um instante universal. Um evento chega ao servidor, outro chega ao cliente, e uma reconexão pode mudar a ordem em que o usuário percebe as coisas.

Imagine uma pessoa fechando o notebook sem encerrar a aplicação de maneira limpa. Se a interface dos amigos depender apenas do último evento de desconexão, ela poderá continuar online por mais tempo do que deveria. Se o sistema for agressivo demais ao marcar ausência, oscilações momentâneas farão o status piscar.

O mesmo acontece quando há várias sessões abertas. Uma aba perde conexão enquanto o aplicativo desktop continua ativo. Quem representa o estado final daquela pessoa?

A solução não é simplesmente disparar mais eventos. É definir qual informação tem autoridade, quanto tempo ela vale e como o estado é reconciliado quando a conexão volta. Heartbeats, expiração, atualização otimista e sinais de atividade são ferramentas possíveis, mas só ajudam quando seguem um contrato coerente.

Para o usuário, o indicador deve ser estável o bastante para transmitir confiança e responsivo o bastante para ser útil. Esse equilíbrio é tanto engenharia quanto UX.

O caso do AFK deixou isso muito concreto

Um dos fluxos que desenvolvi no PING envolve a identificação de inatividade e a movimentação para um canal AFK nos Espaços. No desktop, é possível usar informações de inatividade do sistema operacional por meio da ponte entre o Electron e a aplicação. Em clientes web, esse tipo de informação não possui a mesma confiabilidade.

Em teoria, parecia direto: detectar um período de inatividade e agir. Na prática, surgiram problemas quando a noção de inatividade da interface não correspondia ao comportamento real da pessoa. Um usuário podia estar participando de uma conversa, sem mover o mouse, e ainda assim continuar presente socialmente.

Havia outra sutileza: atualizar a interface web hospedada não atualiza automaticamente os recursos nativos presentes numa versão antiga do aplicativo desktop. Uma diferença entre renderer e preload pode fazer a mesma funcionalidade ter comportamentos diferentes dependendo da versão instalada.

Isso me forçou a tratar sinais desconhecidos como desconhecidos — e não como prova de ausência. Não receber uma informação confiável é diferente de receber uma confirmação de inatividade.

A especificação do fluxo, os testes e os ajustes de integração passaram a importar tanto quanto a regra de cinco minutos que alguém configurava na tela.

A interface precisa admitir estados intermediários

Há um impulso recorrente no front-end de representar tudo como binário: conectado ou desconectado, carregando ou pronto, presente ou ausente.

Só que produtos de comunicação vivem em transições. Uma pessoa pode estar entrando no canal, reconectando a sessão ou aguardando a confirmação de que sua presença foi reconhecida pelo restante do Espaço.

Quando escondemos tudo isso atrás de um único spinner, o produto parece lento mesmo que parte da operação já tenha acontecido. Quando mostramos a pessoa como conectada antes de validar a participação efetiva, o produto parece rápido, mas pode mentir.

Esse é um problema que ainda exige refinamento: reduzir a latência percebida sem antecipar estados que o sistema ainda não confirmou.

Prefiro pensar em uma sequência clara: intenção de entrar, conexão em andamento, presença confirmada. Cada estado tem um feedback adequado, um caminho de recuperação e um limite sobre o que a interface pode afirmar.

O custo de uma abstração aparentemente conveniente

Em algum momento é tentador criar um único objeto global de presença e deixar cada componente interpretá-lo como quiser. A home lê de um jeito, a lista de amigos de outro e o painel de voz aplica suas próprias exceções.

Isso funciona até os comportamentos começarem a divergir.

Uma abordagem melhor é explicitar o contrato: quais estados existem, qual a origem de cada sinal, o que significa atividade em cada contexto e quais transições são permitidas. A interface consome uma representação coerente, mas não precisa carregar regras de negócio espalhadas em componentes visuais.

Esse raciocínio também evita uma armadilha: transformar um caso especial em regra global. Estar sem mexer no mouse não deveria, por padrão, desfazer uma participação legítima em áudio.

O aprendizado vai além do PING

Toda vez que vejo uma bolinha verde agora, lembro que ela não representa apenas um estado de CSS. Representa uma decisão sobre tempo, confiança e comportamento humano.

Em dashboards, a mesma discussão aparece em indicadores “ao vivo”. Em sistemas colaborativos, aparece em cursores e editores simultâneos. Em ferramentas operacionais, aparece em status de processamento. A interface pode ser mínima, mas o contrato que a sustenta precisa ser preciso.

Construir presença no PING me ensinou que o objetivo não é exibir atualizações o mais rápido possível. É fazer com que a informação continue verdadeira o suficiente para orientar uma ação.

No fim, uma bolinha verde só parece simples quando toda a complexidade ao redor foi bem resolvida.

Este texto faz parte de uma série sobre a construção do PING. No próximo, vou abordar por que o sucesso de uma chamada não termina quando os dois participantes se conectam.

Share on

WEEKLY NOTE / NEWSLETTER

Enjoyed this insight?

Get weekly reflections on technology, product, and execution decisions.

No spam. Only content worth opening.

Related notes

03