Álbum Copa do Mundo 2026
Caderno de 994 figurinhas que precisa funcionar na banca de troca, onde não há rede: grava offline, sincroniza depois e lê o código do cromo por foto.
- No ar
- offline-first
- 994 figurinhas
- OCR no aparelho
- Next.js
- TypeScript
- Cloudflare Workers
- D1
- Drizzle ORM
- IndexedDB
- PP-OCRv5
- Tailwind CSS
- shadcn/ui
- Vitest
- Playwright
O problema
O álbum da Panini da Copa de 2026 tem 994 figurinhas. Quem coleciona sabe de cor umas trinta e erra o resto — e erra caro, porque comprar repetida é dinheiro fora. O controle costuma viver numa lista de papel ou numa nota do celular, que serve enquanto ninguém pergunta “você tem a KSA 14?” no meio de uma roda de troca.
O detalhe que decide a arquitetura inteira é geográfico: os lugares onde o álbum é usado — a banca, o portão da escola, a mesa de troca na casa de alguém — são exatamente os lugares de pior sinal. Um app que precisa de rede para registrar uma figurinha é pior que o papel que ele substitui, porque o papel nunca falha em silêncio.
Somam-se duas restrições que vieram do dono: um único usuário e custo zero de operação.
Offline não é modo degradado — é o modo normal
A regra que organiza todo o resto: a rede nunca fica no caminho entre o toque e o número na tela. Marcar uma figurinha grava primeiro no banco do próprio navegador e devolve a interface atualizada na hora. O servidor descobre depois.
Entre dois aparelhos vence o carimbo de tempo mais recente por figurinha. Para uma pessoa com celular e desktop isso é exato, e custa uma coluna em vez de uma biblioteca de resolução de conflito. O catálogo — 48 seleções e as figurinhas especiais — nunca muda em uso: é semeado no servidor uma vez e copiado para o aparelho na primeira carga, então a única coisa que trafega depois é a posse.
Ler a figurinha por foto
O gesto mais caro do app era digitar. Ninguém quer teclar KSA 14 com uma pilha de figurinhas na
mão — e o código está impresso no verso de cada uma. Então a câmera passou a ser um caminho de
entrada.
O ponto que faz diferença é onde a leitura acontece: o motor de reconhecimento roda no próprio aparelho, servido pelo mesmo domínio do app. Modelo e runtime somam cerca de 26 MB, buscados só quando alguém abre a tela de leitura e guardados pelo service worker a partir daí. Nenhuma foto sai do dispositivo, nenhuma chamada vai para serviço de terceiro, e a leitura continua funcionando offline — o que era o requisito desde o começo, já que ler figurinha é justamente o que se faz na banca.
Duas decisões seguram a precisão. A primeira é a normalização da imagem antes da leitura: foto de celular moderno chega com milhares de pixels de largura e a leitura fica confiável numa faixa bem mais estreita, então toda imagem — de câmera ou de arquivo — passa pelo mesmo redimensionamento num ponto único do código.
A segunda é que o app nunca grava sozinho. A leitura sempre termina numa pergunta com o nome do jogador junto — “KSA14 — Saleh Abu Alshamat?” — e só o toque em Confirmar mexe na coleção. Quando o motor lê lixo, a resposta é honesta: “não consegui ler”, em vez de um chute plausível. Num álbum, um chute plausível é pior que nenhuma leitura, porque some sem deixar rastro dentro de 994 linhas.
As fotos reais que o dono tirou na mesa da cozinha viraram fixtures de regressão. A troca de motor só entrou depois de passar nessa bateria inteira.
O que separa um checklist de uma ferramenta de troca
Marcar posse é o mínimo. O que o colecionador faz de verdade é conversar com outro colecionador, e a moeda dessa conversa é uma lista de texto colada num aplicativo de mensagem.
Daí sai o recurso que fecha o ciclo: a tela de comparação aceita a lista do outro, colada como texto, e cruza com a coleção local para responder as duas perguntas da negociação — o que eu posso dar e o que ele pode me dar. O leitor de texto não exige formato: reconhece a lista exportada pelo próprio app, mas também texto solto com siglas e números, com ou sem cabeçalho, com ou sem a quantidade entre parênteses. Quando não reconhece nada, diz isso em vez de mostrar uma tabela vazia.
No mesmo espírito, a entrada em massa aceita faixas — abrir um pacote e registrar 1-20, 34, 55
de uma vez, somando ou retirando — porque a alternativa é vinte toques na grade.
A conta que o colecionador realmente faz
A pergunta que ninguém responde com uma barra de progresso é: quanto ainda vou gastar? As últimas figurinhas são as caras — quanto menos falta, mais pacote se compra para achar uma nova.
A tela de estatísticas usa esse comportamento a favor do usuário: estima quantos pacotes ainda devem ser necessários, converte em dinheiro com um preço de pacote que a pessoa edita, e compara o ritmo atual com o ritmo necessário para fechar o álbum até a data-limite. A evolução vem dos próprios carimbos de tempo das marcações — é aproximada, e a tela diz que é.
Duas peles, alvo de dedo
O app é usado em pé, com uma mão, às vezes num lugar mal iluminado. Isso pesou mais que estética: alvos de toque grandes, estado indicado por cor e por ícone, e um tema escuro de verdade — não um filtro, mas uma segunda paleta com contraste verificado nos dois modos.
A figurinha possuída avança visualmente e a faltante recua — o inverso do padrão de lista de tarefas, onde o item pendente grita. Aqui o que se procura na grade é o buraco, e buraco se acha mais rápido quando o resto está cheio.
As decisões que sustentam o custo zero
O app inteiro roda num Worker na borda, com o banco no SQLite gerenciado da mesma plataforma. Não há servidor ligado esperando requisição, e por isso não há conta no fim do mês.
O login é a decisão mais econômica do projeto: em vez de escrever cadastro, sessão e recuperação de senha para um usuário, o app fica atrás de um gate de identidade da própria plataforma. Zero linha de código de autenticação, zero senha guardada — e, em troca, o pitfall do redirecionamento que abre este caso, que virou o primeiro risco documentado no design e tem teste próprio.
O link deste caso, portanto, passa por esse login: o app está no ar, mas a coleção é de uma pessoa só. Os prints acima são a visita guiada.
Estado
No ar, com o catálogo real de 994 figurinhas conferido contra o checklist impresso. A suíte de unidade tem 551 casos em 65 arquivos, todos verdes, e quatro suítes de ponta a ponta guardam os fluxos que só falham rodando: a volta completa de exportar e importar, o uso offline, a convergência entre dois aparelhos e o registro do service worker atrás do gate de login.
Quer conversar sobre este projeto — ou sobre construir algo assim? Fale comigoou escreva para contato@daniel-dac.com.