// PROTÓTIPO FUNCIONAL · AO VIVO
Ingestão de dados públicos ao vivo, detecção de anomalias e busca de padrões similares via IA, transmitido por WebSocket para um dashboard que atualiza sozinho.
Muita operação depende de decisões em cima de dados que mudam a cada minuto — estoque, sensores, preços, filas — mas boa parte dos dashboards ainda são "snapshots" que só atualizam quando alguém aperta F5. Construir ingestão contínua, detecção de padrões e um canal ao vivo até o usuário é um problema de arquitetura, não só de front-end.
Este projeto é um protótipo funcional rodando em produção (não uma maquete): ele consome uma API pública de clima em tempo real, roda cada leitura por um detector de anomalias e uma busca de padrões similares, e transmite tudo via WebSocket assim que acontece.
// ARCHITECTURE
Um loop de coleta busca dados reais a cada 60 segundos, cada leitura passa por dois detectores independentes de IA, e o resultado combinado é transmitido para todos os clientes conectados — sem polling do lado do navegador.
Loop assíncrono coleta dados reais de múltiplas cidades a cada 60s, via um cliente isolado e substituível (mesmo padrão de adapter plugável do projeto de extração de documentos).
Z-score sobre uma janela móvel, por cidade e por métrica — totalmente explicável, sem caixa-preta.
Cada leitura vira um vetor numérico; uma busca por similaridade encontra o registro histórico mais parecido, de qualquer cidade.
O dashboard não faz polling: o servidor empurra cada atualização assim que ela é processada.
// EM PRODUÇÃO
Hospedado no Railway, consumindo a API pública Open-Meteo sem chave, sem dados sintéticos:
Duas decisões de engenharia que valeram a pena documentar:
A primeira versão usava ChromaDB para a busca de padrões. Em produção, o container era derrubado e reiniciado a cada ~60-70s — consistente com falta de memória — o que derrubava toda conexão WebSocket aberta. Para o volume de dados real do app (poucos vetores de 5 números por cidade), um banco vetorial completo era peso desnecessário: troquei por uma busca por força bruta em memória, mesma interface, sem a dependência pesada. Resolveu o problema.
A segunda foi mais boba: um erro de maiúscula na URL do CDN do Chart.js quebrava o carregamento do gráfico — e como o script inteiro rodava em um único bloco, esse erro impedia até o WebSocket de conectar. Corrigido, e agora a falha de qualquer biblioteca de gráfico é isolada: o dashboard continua funcionando (cards + insights) mesmo que o gráfico não carregue.