- Papel: criador e único desenvolvedor
- Período: desde novembro de 2024
- Plataformas: Android, iPhone e iPad
- Em números: 545 usuários, 554 notas fiscais processadas e 5.961 preços publicados
- Disponível em: Google Play · App Store · buscapreco.net
Começou com o preço do café
Como funciona
- Escaneie a nota. O app lê o QR code e o backend busca os itens no portal da SEFAZ. Cada item vira um preço registrado, com data e mercado.
- Consulte um produto. Pelo nome ou pelo código de barras, você vê o preço nos mercados próximos e como ele variou ao longo do tempo.
- Compare mercados. Monte uma lista de compras e o app estima o total em cada mercado da região. Depois da compra, ele mostra quanto você economizou em relação aos outros.
Arquitetura
Os desafios
Ler notas fiscais sem uma API
Uma busca que entende "leite"
| Busca | Primeiro resultado (antes) | Primeiro resultado (depois) |
|---|---|---|
| leite | Creme de leite | Leite integral |
| papel higiênico | Tapete higiênico | Papel higiênico |
- Busca textual completa com dicionário em português e sem acentos: "higiênico" e "higienico" viram o mesmo termo, e resultados que contêm todas as palavras buscadas vêm antes dos demais.
- Pesos por campo: casar no nome vale mais que casar na marca.
- Posição da palavra: "Leite integral" começa com o termo buscado e "Creme de leite" não. Foi esse sinal que resolveu o caso do leite.
- Trigramas como plano B, quando nada casa, para continuar tolerando erros de digitação.
- Popularidade como desempate, calculada a partir da quantidade de preços recentes de cada produto.
Produtos a granel: o mesmo corte com dez nomes
Do Android ao iOS sem reescrever o app
| Recurso | Android | iOS |
|---|---|---|
| Câmera e leitura de códigos | CameraX + ML Kit | AVFoundation + Vision |
| Assinaturas | Google Play Billing | StoreKit 2 |
| Localização | Google Play Services | CoreLocation |
Outros problemas que valeram a pena
- Dados de produto. No Brasil, as bases de códigos de barras são, em sua maioria, fechadas. O app consulta primeiro o Open Food Facts, que tem licença aberta, e dá os créditos devidos. Quando o produto não está lá, ele é criado a partir da própria nota (onde aparece como "LEITE UHT INTEGRAL ITAMBE 1L"), e a comunidade pode completar o cadastro com foto e dados. Os envios passam por uma triagem automática de imagens impróprias e depois por moderação manual. A categoria é atribuída automaticamente pelo código NCM, a classificação fiscal que já vem em cada item da nota.
- Onde fica esse mercado? A nota traz o CNPJ, a razão social e o endereço, mas não traz coordenadas nem o nome pelo qual as pessoas conhecem a loja. O backend geocodifica o endereço, busca estabelecimentos próximos e escolhe o candidato pelo número do endereço e pela semelhança do nome. Quando erra, quem registrou o mercado pode escolher outro candidato, e no painel eu corrijo pelo mapa.
- O problema do ovo e da galinha. Um app colaborativo vazio não tem valor, e sem valor ninguém contribui. Por isso, consultar preços consome créditos: uma parte se renova todo dia, para quem só quer usar, e outra é ganha ao contribuir, sendo que notas com mais itens rendem mais. Níveis de experiência dão uma sensação de progresso, e a assinatura remove os limites. Também existem proteções contra abuso, que, por motivos óbvios, não vou detalhar aqui.
Onde o projeto está hoje
- 545 usuários
- 554 notas fiscais processadas
- 5.961 preços publicados
O que aprendi
- Registre a origem dos dados desde o primeiro dia. Nas primeiras versões, eu também usava outras fontes de dados de produto. Quando revisei o licenciamento, decidi ficar só com fontes abertas e com o que a comunidade envia, mesmo perdendo cobertura. A migração reconsultou o catálogo inteiro e removeu as imagens cuja licença não era compatível. Ela teria sido bem mais simples se eu soubesse de onde veio cada registro: dois terços do catálogo não tinham essa informação, e a única saída segura foi reprocessar todos.
- Ter uma pessoa no circuito é uma funcionalidade, não uma gambiarra. Mercados, granel, produtos enviados: em todos esses casos, o melhor desenho foi o algoritmo sugerir e uma pessoa confirmar, com decisões reversíveis.
- Use o banco que você já tem até ele realmente não dar conta. O PostgreSQL resolveu busca textual, tolerância a erros de digitação e ranking sem mais um sistema para operar.
- Isole o que é frágil. A parte mais instável do sistema, a leitura dos portais, vive num serviço próprio e não derruba o resto quando falha.
- Escreva antes de programar. Antes de cada funcionalidade relevante, escrevo um documento curto de design com o contexto, as decisões e o que fica de fora. Hoje são mais de 60, e foram eles que tornaram este texto possível.
Tecnologias
- Mobile: Kotlin Multiplatform, Compose Multiplatform, Ktor, Koin
- Backend: Kotlin, Spring Boot 3, Spring Security (OAuth2), JPA, Flyway, OpenFeign, Testcontainers
- Dados: PostgreSQL (busca textual e pg_trgm), Redis, S3
- Leitura de notas: Python, Flask, Selenium
- Painel de moderação: React, TypeScript, Vite, Tailwind, TanStack Query
- Site: Astro
- Autenticação: Keycloak (OIDC, login social)
- Infraestrutura: VPS própria, Docker Swarm, Cloudflare, Prometheus
- Integrações: Open Food Facts, Google Places e Geocoding, Cloud Vision, Firebase Cloud Messaging, Google Play Billing, StoreKit 2
Links
- Site: buscapreco.net
- Google Play: Busca Preço
- App Store: Busca Preço: Compras



