diff --git a/README.md b/README.md index 30489b4..34e544d 100644 --- a/README.md +++ b/README.md @@ -1,539 +1,253 @@ # NutriScan -
+**Consulta nutricional de produtos de supermercado: busca por nome ou código de barras na base colaborativa do Open Food Facts, mostra Nutri-Score e grau de processamento (NOVA) e organiza listas de compras, com cache local para continuar funcionando sem internet.** -![NutriScan Logo](./public/apple-touch-icon.png) +![Next.js](https://img.shields.io/badge/Next.js-15-black?logo=nextdotjs&logoColor=white) +![React](https://img.shields.io/badge/React-19-61DAFB?logo=react&logoColor=black) +![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178C6?logo=typescript&logoColor=white) +![Prisma](https://img.shields.io/badge/Prisma-6-2D3748?logo=prisma&logoColor=white) +![SQLite](https://img.shields.io/badge/SQLite-3-003B57?logo=sqlite&logoColor=white) +![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-3.4-06B6D4?logo=tailwindcss&logoColor=white) +![Node](https://img.shields.io/badge/Node-%3E%3D18.18-5FA04E?logo=nodedotjs&logoColor=white) +![Licença](https://img.shields.io/badge/licen%C3%A7a-uso%20pessoal-lightgrey) -**Plataforma completa de informações nutricionais alimentares** +Demonstração publicada pelo autor: -_Descubra o que a comunidade alimentar sabe sobre seus alimentos_ +## Sobre -[![Next.js](https://img.shields.io/badge/Next.js-14.2.18-black?style=for-the-badge&logo=next.js&logoColor=white)](https://nextjs.org/) -[![TypeScript](https://img.shields.io/badge/TypeScript-5.7.2-blue?style=for-the-badge&logo=typescript&logoColor=white)](https://www.typescriptlang.org/) -[![Prisma](https://img.shields.io/badge/Prisma-5.22.0-2D3748?style=for-the-badge&logo=prisma&logoColor=white)](https://www.prisma.io/) -[![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-3.4.15-38B2AC?style=for-the-badge&logo=tailwind-css&logoColor=white)](https://tailwindcss.com/) -[![Open Food Facts](https://img.shields.io/badge/Open_Food_Facts-API-4CAF50?style=for-the-badge&logo=openfoodfacts&logoColor=white)](https://world.openfoodfacts.org/) +Saber o que um produto industrializado tem de verdade exige consultar bases públicas e cruzar informação espalhada: nota Nutri-Score, grau de processamento, alérgenos, aditivos e tabela nutricional. O NutriScan junta isso em uma interface só. -[![Live Demo](https://img.shields.io/badge/Live_Demo-00B37E?style=for-the-badge&logo=vercel&logoColor=white)](https://nutriscan.evandro.dev.br) -[![Report Bug](https://img.shields.io/badge/Report_Bug-E62117?style=for-the-badge&logo=github&logoColor=white)](https://github.com/evandrodevbr/lista-compras/issues) -[![Request Feature](https://img.shields.io/badge/Request_Feature-2EA043?style=for-the-badge&logo=github&logoColor=white)](https://github.com/evandrodevbr/lista-compras/issues) +A aplicação consulta a base do Open Food Facts (mais de 2 milhões de produtos), aceita busca por texto ou por código de barras (8 a 13 dígitos, com detecção automática do tipo) e exibe Nutri-Score e grau de processamento NOVA de cada produto. O painel de filtros avançados oferece classificação nutricional, categorias, marcas, alérgenos, aditivos e faixas de valores nutricionais, com 12 opções de ordenação. Além da consulta, mantém listas de compras persistidas em SQLite. -
+O ponto de arquitetura que diferencia o projeto é o cache em duas camadas: um arquivo JSON no servidor, versionado no repositório, com os produtos já vistos, e um cache no `localStorage` do navegador. Com o modo cache-only ligado, a aplicação responde apenas com o cache local, sem chamar a API externa. -## 📋 Índice +## Como funciona -- [Sobre o Projeto](#-sobre-o-projeto) -- [Demonstração Visual](#-demonstração-visual) -- [Funcionalidades](#-funcionalidades) -- [Stack Tecnológica](#-stack-tecnológica) -- [Arquitetura](#-arquitetura) -- [Instalação e Setup](#-instalação-e-setup) -- [API e Integrações](#-api-e-integrações) -- [Database Schema](#-database-schema) -- [Performance e Otimizações](#-performance-e-otimizações) -- [Deployment](#-deployment) -- [Scripts Disponíveis](#-scripts-disponíveis) -- [Contribuindo](#-contribuindo) -- [Licença](#-licença) -- [Contato](#-contato) -- [Agradecimentos](#-agradecimentos) +``` +navegador + │ + ├─ páginas Next.js (App Router, Server Components + Client Components) + │ + ├─ /api/search ──────────────▶ data/products-cache.json (cache do servidor, 232 produtos) + │ └─ se faltam resultados ─▶ Open Food Facts (world.openfoodfacts.org/cgi/search.pl) + ├─ /api/products/[barcode] ──▶ cache JSON ─▶ Open Food Facts (api/v2/product/{code}.json) + │ └─ produto novo é gravado no cache JSON + ├─ /api/location ────────────▶ headers do proxy ou api.ipify.org (país do usuário) + └─ /api/storage-stats ───────▶ estatísticas do cache JSON -## 🚀 Sobre o Projeto +listas de compras: componentes ─▶ Server Actions (app/actions.ts) ─▶ Prisma ─▶ SQLite +cache do cliente: resultados de busca e filtros no localStorage (TTL configurável) +``` -**NutriScan** é uma plataforma web moderna que democratiza o acesso a informações nutricionais transparentes e confiáveis. Desenvolvida com foco na experiência do usuário e performance, a aplicação conecta consumidores conscientes à maior base de dados colaborativa de alimentos do mundo. +- Produto não encontrado no cache JSON é buscado na API e salvo no cache, o que aumenta o acervo offline a cada uso. +- A rota `/api/search` pagina em blocos de 1000 resultados na API externa, com pausa de 200 ms entre requisições. +- Não há autenticação nem multiusuário: cada lista de compras é identificada por um id na URL. -### 🎯 Missão +## Stack -Empoderar usuários com dados nutricionais precisos e abrangentes para tomada de decisões alimentares mais conscientes através de uma plataforma intuitiva, rápida e confiável. +| Camada | Escolha | +|---|---| +| Framework | Next.js 15 (App Router, Server Actions, Route Handlers) | +| UI | React 19, shadcn/ui sobre Radix UI, Tailwind CSS 3.4, Framer Motion 11, lucide-react 0.460 | +| Tema | next-themes 0.4 (claro e escuro, persistido) | +| Linguagem | TypeScript 5.9 em modo `strict` | +| Listas de compras | SQLite com Prisma 6 (`prisma/schema.prisma`) | +| Dados de produtos | API pública do Open Food Facts + cache JSON em `data/` | +| Cache do cliente | `localStorage`, com modo cache-only | +| Pacotes | pnpm (lockfile versionado) | +| Deploy | nixpacks (`nixpacks.toml`) e Dokploy (`dokploy.yaml`) | -### ⭐ Diferenciais +## Requisitos -- **Dados Colaborativos**: Acesso a milhões de produtos da maior base de dados open source do mundo -- **Filtros Avançados**: Sistema sofisticado de busca e filtros para descoberta precisa de produtos -- **Classificações de Saúde**: Nutri-Score e NOVA group para avaliação rápida da qualidade -- **Atualizações em Tempo Real**: Sincronização de dados ao vivo e resultados instantâneos -- **Arquitetura Moderna**: Desenvolvida com tecnologias de ponta e foco em performance +- Node.js `>=18.18` (o deploy fixa Node 18; o build foi verificado em Node 24.20.0) +- pnpm 10 ou superior (o deploy fixa 10.34.5; a instalação foi verificada com pnpm 12.4.1 e a resolução de dependências foi verificada com pnpm 10.34.5) +- Nenhum serviço externo é obrigatório para subir a aplicação: sem internet ela responde pelo cache local -### 📊 Estatísticas +## Início rápido -| Métrica | Valor | -| ------------------- | ----- | -| Produtos no banco | 2M+ | -| Países cobertos | 100+ | -| Disponibilidade | 24/7 | -| Dados colaborativos | Sim | +```bash +git clone https://github.com/evandrodevbr/nutriscan.git +cd nutriscan -## 📱 Demonstração Visual +pnpm install # o postinstall roda `prisma generate` +cp .env.example .env +pnpm db:push # cria as tabelas Lista e Produtos no SQLite +pnpm dev # http://localhost:3000 +``` -> **Nota**: Screenshots serão adicionados em breve mostrando as principais funcionalidades da aplicação. +Duas pegadinhas que quebram a primeira execução e estão resolvidas acima: -### Principais Telas +- O arquivo de ambiente precisa se chamar `.env`, não `.env.local`: a CLI do Prisma (`prisma generate`, `prisma db push`) só lê `.env`. O Next.js lê os dois. +- `pnpm db:migrate` roda `prisma migrate deploy` e não cria nada aqui, porque o repositório não tem a pasta `prisma/migrations`. Quem cria o schema é `pnpm db:push`. -- **Página Inicial**: Interface de busca com hero section e barra de pesquisa -- **Resultados**: Lista de produtos com filtros avançados e ordenação -- **Detalhes do Produto**: Informações nutricionais completas e classificações -- **Lista de Compras**: Gerenciamento de produtos com quantidades e status -- **Modos de Tema**: Visualização em tema claro e escuro +Com o servidor no ar: -## ✨ Funcionalidades +```bash +curl -s "http://localhost:3000/api/search?q=bis&cache_only=true&page_size=5" +curl -s http://localhost:3000/api/storage-stats +``` -### 🔍 Sistema de Busca Inteligente +## Uso -O NutriScan oferece múltiplas formas de encontrar produtos alimentícios: +| Rota | O que é | +|---|---| +| `/` | Página inicial com busca por nome ou código de barras | +| `/resultados?q=` | Resultados com filtros, ordenação e paginação | +| `/produto/` | Detalhe do produto: Nutri-Score, grupo NOVA, composição por 100 g e lista de ingredientes | +| `/lista/` | Lista de compras: adicionar item com quantidade e unidade, marcar como comprado, remover | +| `/sobre` | Página institucional do projeto | +| `/robots.txt`, `/sitemap.xml` | Gerados pelo Next.js | -- **Busca por Código de Barras**: Reconhecimento automático de códigos de 8-13 dígitos -- **Busca por Nome/Marca**: Pesquisa textual inteligente com sugestões -- **Detecção Automática**: Sistema que identifica o tipo de busca automaticamente -- **Geolocalização**: Priorização de produtos locais baseada na localização do usuário -- **API Proxy**: Chamadas seguras através de rotas Next.js para evitar problemas de CORS +## API -### 💾 Sistema de Cache Avançado +Todas as rotas ficam em `app/api` e são Route Handlers do Next.js. -Sistema multi-camada de cache para performance otimizada: +| Rota | Método | O que faz | +|---|---|---| +| `/api/search` | GET | Busca produtos no cache JSON e, se faltar, no Open Food Facts | +| `/api/products/[barcode]` | GET | Busca um produto pelo código de barras (cache primeiro, depois API) | +| `/api/location` | GET | País estimado a partir do IP (`x-forwarded-for`, `x-real-ip` ou api.ipify.org) | +| `/api/cache/sync` | POST | Grava um lote de produtos no cache JSON. Corpo: `{ "products": [...] }` | +| `/api/storage-stats` | GET | Total de produtos, tamanho do arquivo e data da última atualização do cache | -- **Cache localStorage**: Armazenamento local com TTL configurável -- **Cache de Buscas**: Armazenamento completo de buscas com filtros aplicados -- **Cache JSON**: 218 produtos pré-carregados para uso offline -- **Modo Cache-Only**: Funcionamento completo sem conexão com internet -- **Sincronização Inteligente**: Atualização automática de dados quando online -- **Estatísticas de Storage**: Monitoramento de uso de armazenamento +Parâmetros de `/api/search`: -### 🎛️ Filtros e Ordenação +| Parâmetro | Valores | Observação | +|---|---|---| +| `q` | texto | Obrigatório; sem ele a rota responde 400 | +| `page`, `page_size` | inteiros `>= 1` | Padrão 1 e 20; valores inválidos respondem 400 | +| `cache_only` | `true` | Responde só com o cache local, sem chamar a API externa | +| `country` | código do país | Enviado como `countries_tags_en` | +| `countries`, `categories`, `brands` | tags | Filtros repassados como `countries_tags`, `categories_tags`, `brands_tags` | +| `nutrition_grades`, `nova_groups` | `a` a `e`, `1` a `4` | Filtros de classificação | +| `allergens`, `exclude_allergens`, `additives`, `exclude_additives`, `no_additives` | tags, `true` | Filtros de composição | +| `energy_min`, `energy_max`, `fat_min`, `fat_max`, `carbohydrates_min`, `carbohydrates_max`, `proteins_min`, `proteins_max`, `sugars_min`, `sugars_max`, `fiber_min`, `fiber_max`, `sodium_min`, `sodium_max` | número (por 100 g) | Faixas nutricionais | +| `sort_by` | `nutrition_grade`, `name`, `brand`, `energy`, `fat`, `sugars` | Ordenação; o padrão é `popularity` | +| `sort_order` | `asc`, `desc` | Padrão `asc` | -Sistema robusto de filtros para descoberta precisa: +No modo `cache_only` a busca considera apenas texto (nome, marca, categoria) e país; os demais filtros só são repassados para o Open Food Facts nas buscas online. -#### Classificações de Saúde +Exemplo de resposta de `/api/search`: -- **Nutri-Score**: Filtro por classificação A-E (muito bom a muito ruim) -- **NOVA Group**: Filtro por nível de processamento 1-4 (não processado a ultraprocessado) +```json +{ + "products": [{ "code": "7622210575975", "product_name": "Bis", "brands": "Lacta" }], + "count": 5, + "page": 1, + "page_size": 5, + "fromCache": true, + "fromAPI": false, + "cacheStats": { "localProducts": 5, "apiProducts": 0, "newProducts": 0, "totalReturned": 5 } +} +``` -#### Filtros de Produto +## Produção -- **Categorias**: Filtro por tipo de alimento (bebidas, laticínios, snacks, etc.) -- **Marcas**: Filtro por fabricante -- **Alérgenos**: Identificação e filtro por substâncias alergênicas -- **Aditivos**: Filtro por aditivos alimentares e conservantes +```bash +pnpm build # prisma generate + next build +pnpm start # next start, porta 3000 (use -p para trocar) +``` -#### Filtros Nutricionais +O `build` precisa de `DATABASE_URL` no ambiente para gerar o Prisma Client, e o `start` precisa dela para as rotas de lista de compras. -- **Ranges Personalizados**: Filtros por valores nutricionais (calorias, gorduras, açúcares, etc.) -- **12 Opções de Ordenação**: Por relevância, nutrição, nome, marca, valores nutricionais, etc. +## Deploy -### 🛒 Listas de Compras Colaborativas +O repositório traz duas configurações de build, ambas para plataformas que usam nixpacks: -Sistema completo de gerenciamento de compras: +- `nixpacks.toml`: Node 18 e pnpm 10.34.5, instala com `--no-frozen-lockfile`, roda `prisma generate`, `prisma db push --accept-data-loss` e o build, com `DATABASE_URL=file:./db/database.sqlite`. O start é `pnpm start` com a mesma variável. +- `dokploy.yaml`: repete os passos de instalação (`pnpm install --no-frozen-lockfile`), geração do Prisma Client e build. -- **Múltiplas Listas**: Criação e gerenciamento de várias listas de compras -- **Produtos Detalhados**: Adição com quantidade, unidade e observações -- **Status de Compra**: Marcação de itens como comprados -- **Sincronização**: Persistência via Prisma + SQLite -- **Compartilhamento**: Compartilhamento de listas via ID único +Como o `DATABASE_URL` do deploy aponta para `file:./db/database.sqlite` e o caminho relativo do SQLite é resolvido a partir da pasta `prisma/`, o banco de produção fica em `prisma/db/database.sqlite` no contêiner, separado do arquivo versionado no repositório. -### 🎨 Interface e Experiência do Usuário - -Design moderno e acessível: - -- **Design Responsivo**: Mobile-first com adaptação para todos os dispositivos -- **Temas**: Modo claro e escuro com persistência de preferência -- **Animações**: Transições suaves com Framer Motion -- **Acessibilidade**: Componentes Radix UI com suporte completo a leitores de tela -- **Estados de Loading**: Skeletons e indicadores de carregamento -- **Paginação Otimizada**: Carregamento eficiente de grandes listas -- **Imagens Otimizadas**: Lazy loading e otimização automática - -## 🛠 Stack Tecnológica - -### Framework Principal - -- **[Next.js 14.2.18](https://nextjs.org/)** - React framework com App Router e Server Actions -- **[TypeScript 5.7.2](https://www.typescriptlang.org/)** - JavaScript tipado para maior confiabilidade -- **[React 18.3.1](https://react.dev/)** - Biblioteca de interface moderna com recursos concorrentes - -### Banco de Dados e ORM - -- **[Prisma 5.22.0](https://www.prisma.io/)** - ORM type-safe para gerenciamento de dados -- **[SQLite](https://www.sqlite.org/)** - Banco de dados leve e serverless - -### Estilização e UI - -- **[Tailwind CSS 3.4.15](https://tailwindcss.com/)** - Framework CSS utility-first -- **[shadcn/ui](https://ui.shadcn.com/)** - Biblioteca de componentes reutilizáveis -- **[Radix UI](https://www.radix-ui.com/)** - Primitivos acessíveis não estilizados -- **[Lucide Icons 0.460.0](https://lucide.dev/)** - Ícones bonitos e customizáveis -- **[Framer Motion 11.12.0](https://www.framer.com/motion/)** - Biblioteca de animações - -### APIs Externas - -- **[Open Food Facts](https://world.openfoodfacts.org/)** - Base de dados global de produtos alimentícios -- **Geolocation API** - Recomendações baseadas em localização - -### Ferramentas de Desenvolvimento - -- **[ESLint 8.57.1](https://eslint.org/)** - Linting e formatação de código -- **[PostCSS 8.4.49](https://postcss.org/)** - Processamento de CSS -- **[pnpm](https://pnpm.io/)** - Gerenciador de pacotes eficiente - -## 🏗 Arquitetura - -### Estrutura do App Router +## Estrutura do projeto ``` app/ -├── actions.ts # Server Actions para mutações de dados -├── api/ # Rotas de API para proxies de serviços externos -│ ├── cache/sync/ # Sincronização de cache -│ ├── location/ # Serviços de geolocalização -│ ├── products/[barcode]/ # Proxy de busca de produto -│ ├── search/ # Proxy de busca Open Food Facts -│ └── storage-stats/ # Estatísticas de armazenamento -├── components/ # Componentes específicos de funcionalidades -│ ├── landing/ # Seções da página inicial -│ └── [componentes diversos] # Componentes reutilizáveis -├── lista/[id]/ # Páginas de lista de compras -├── produto/[barcode]/ # Páginas de detalhes do produto -├── resultados/ # Página de resultados de busca -└── layout.tsx # Layout raiz +├── page.tsx página inicial (hero, recursos, como funciona, doação) +├── sobre/ página institucional +├── resultados/ busca com filtros, ordenação e paginação +├── produto/[barcode]/ detalhe do produto +├── lista/[id]/ lista de compras +├── api/ search, products/[barcode], location, cache/sync, storage-stats +├── actions.ts Server Actions das listas (criar, listar, marcar, remover) +├── components/ componentes de tela (landing/, cards, filtros, paginação) +├── layout.tsx layout raiz: fontes, metadados, analytics +├── robots.ts, sitemap.ts metadados de indexação +├── globals.css estilos globais e tokens de tema +├── fonts/ fontes Geist +hooks/ busca, filtros, cache, geolocalização e monitor de storage +lib/ +├── openFoodFactsApi.ts cliente da API do Open Food Facts e ordenação +├── jsonCacheManager.ts cache JSON do servidor (data/products-cache.json) +├── cacheManager.ts cache de buscas no localStorage +├── geolocation.ts detecção de país do usuário +├── searchUtils.ts ordenação por relevância +├── types.ts tipos compartilhados +└── prisma.ts singleton do Prisma Client +components/ui/ componentes shadcn/ui (button, dialog, select, sheet, ...) +prisma/schema.prisma modelos Lista e Produtos +data/products-cache.json cache inicial com 232 produtos +docs/ documentação interna +nixpacks.toml, dokploy.yaml configuração de deploy ``` -### Fluxo de Dados - -1. **Requisições de Busca**: Entrada do usuário → Rota de API → API Open Food Facts → Resposta -2. **Gerenciamento de Listas**: Ações do usuário → Server Actions → Prisma → Banco de dados -3. **Atualizações em Tempo Real**: Server Actions → Banco de dados → Revalidação → Atualização da UI - -### Sistema de Cache - -```mermaid -graph TD - A[Usuário] --> B[Interface] - B --> C{Cache Local?} - C -->|Sim| D[Retornar Dados] - C -->|Não| E[API Route] - E --> F[Open Food Facts API] - F --> G[Salvar no Cache] - G --> D -``` - -## 🚦 Instalação e Setup - -### Pré-requisitos - -- **Node.js** 18.0 ou superior -- **pnpm** 8.0 ou superior (gerenciador de pacotes recomendado) - -### Instalação Passo a Passo - -1. **Clone o repositório** - - ```bash - git clone https://github.com/evandrodevbr/lista-compras.git - cd lista-compras - ``` - -2. **Instale as dependências** - - ```bash - pnpm install - ``` - -3. **Configure as variáveis de ambiente** - - ```bash - cp .env.example .env.local - ``` - - Configure as seguintes variáveis: - - ```env - DATABASE_URL="file:./prisma/db/database.sqlite" - NEXT_PUBLIC_SITE_URL="http://localhost:3000" - ``` - -4. **Inicialize o banco de dados** - - ```bash - pnpm db:generate - pnpm db:migrate - ``` - -5. **Inicie o servidor de desenvolvimento** - - ```bash - pnpm dev - ``` - -6. **Abra seu navegador** - Navegue para [http://localhost:3000](http://localhost:3000) - -### Troubleshooting - -**Problema**: Erro de conexão com banco de dados - -- **Solução**: Verifique se o arquivo `database.sqlite` existe em `prisma/db/` - -**Problema**: Erro de build do Prisma - -- **Solução**: Execute `pnpm db:generate` antes do build - -**Problema**: Dependências não instaladas - -- **Solução**: Use `pnpm install --no-frozen-lockfile` - -## 🔌 API e Integrações - -### Integração Open Food Facts - -O NutriScan integra com a API Open Food Facts através de um wrapper customizado (`lib/openFoodFactsApi.ts`) que fornece: - -- **Busca de Produtos**: Pesquisa por nome, marca ou categoria -- **Lookup por Código de Barras**: Busca direta usando códigos de barras -- **Filtros Avançados**: Filtros por notas nutricionais, alérgenos, aditivos e mais -- **Cache**: Estratégia de cache inteligente para melhor performance -- **Tratamento de Erros**: Tratamento abrangente de erros e mecanismos de fallback - -### Endpoints Disponíveis - -| Endpoint | Descrição | Método | -| ------------------------- | ----------------------------- | ------ | -| `/api/search` | Busca de produtos | GET | -| `/api/products/[barcode]` | Busca de produto específico | GET | -| `/api/location` | Serviços de geolocalização | GET | -| `/api/cache/sync` | Sincronização de cache | POST | -| `/api/storage-stats` | Estatísticas de armazenamento | GET | - -### Rate Limits e Cache - -- **Resultados de Busca**: Cache de 1 hora para reduzir chamadas à API -- **Detalhes de Produto**: Cache de 24 horas para produtos frequentemente acessados -- **Opções de Filtro**: Cache de 1 semana para dados estáticos como categorias e marcas - -## 🗄 Database Schema - -### Schema Prisma - -```prisma -model Lista { - id String @id - createdAt DateTime @default(now()) - updatedAt DateTime @default(now()) @updatedAt - produtos Produtos[] -} - -model Produtos { - id Int @id @default(autoincrement()) - nome String - qtd Float - tipoUN String - comprado Boolean @default(false) - listaId String @default("default") - createdAt DateTime @default(now()) - updatedAt DateTime @default(now()) @updatedAt - lista Lista @relation(fields: [listaId], references: [id]) -} -``` - -### Características Principais - -- **Estrutura Simples**: Fácil de entender e manter -- **Listas Flexíveis**: Suporte para múltiplas listas de compras -- **Rastreamento de Produtos**: Gerenciamento de quantidade e unidade -- **Rastreamento de Status**: Status de compra para cada item -- **Timestamps**: Rastreamento automático de criação e atualização - -## ⚡ Performance e Otimizações - -### Estratégia de Cache Multi-Camada - -1. **Cache de Busca**: Armazenamento local de resultados de busca -2. **Cache de Produtos**: Cache JSON de produtos populares -3. **Cache de Imagens**: Lazy loading e otimização automática -4. **Cache de API**: Cache de respostas da API Open Food Facts - -### Otimizações de Performance - -- **Lazy Loading**: Carregamento sob demanda de imagens e componentes -- **Code Splitting**: Divisão automática de código por rota -- **Otimização de Bundle**: Minificação e tree-shaking automáticos -- **Server Actions**: Atualizações de dados sem recarregamento de página -- **Image Optimization**: Otimização automática de imagens com Next.js - -### Métricas de Performance - -- **First Load JS**: ~87.3 kB compartilhado -- **Build Time**: Otimizado com Prisma e Next.js -- **Cache Hit Rate**: Monitorado via storage stats API - -## 🚀 Deployment - -### Configuração Dokploy - -O projeto inclui configuração para deployment via Dokploy (`dokploy.yaml`): - -```yaml -build: - pre_build: - - npm install -g pnpm@latest - - export PNPM_HOME="/root/.local/share/pnpm" - - export PATH="$PNPM_HOME:$PATH" - steps: - - name: Verify pnpm - run: which pnpm && pnpm --version - - name: Install dependencies - run: pnpm install --no-frozen-lockfile - - name: Generate Prisma Client - run: pnpx prisma generate - - name: Build application - run: pnpm run build -``` - -### Configuração Nixpacks - -Configuração alternativa para deployment (`nixpacks.toml`): - -```toml -[phases.setup] -nixPkgs = ['nodejs_18', 'openssl'] -cmds = [ - 'npm install -g pnpm@latest', - 'npm install -g prisma' -] - -[phases.install] -cmds = [ - 'npx pnpm install --no-frozen-lockfile', - 'mkdir -p prisma', - 'touch prisma/dev.db', - 'chmod -R 777 prisma' -] - -[phases.build] -cmds = [ - 'mkdir -p node_modules/.prisma', - 'mkdir -p .next', - 'chmod -R 777 node_modules/.prisma node_modules/.bin .next prisma', - 'npx prisma generate', - 'npx prisma db push --accept-data-loss', - 'npx pnpm run build' -] - -[start] -cmd = 'npx pnpm start' -``` - -### Checklist de Deployment - -- [ ] Configurar variáveis de ambiente -- [ ] Executar migrações do banco de dados -- [ ] Gerar Prisma Client -- [ ] Build da aplicação -- [ ] Configurar domínio e SSL -- [ ] Testar funcionalidades principais - -## 📜 Scripts Disponíveis - -### Desenvolvimento - -```bash -pnpm dev # Inicia servidor de desenvolvimento (http://localhost:3000) -pnpm build # Build para produção -pnpm start # Inicia servidor de produção -pnpm lint # Executa ESLint -``` - -### Banco de Dados - -```bash -pnpm db:push # Push do schema Prisma para o banco -pnpm db:generate # Gera Prisma Client -pnpm db:migrate # Executa migrações do banco -``` - -### Pós-instalação - -```bash -pnpm postinstall # Gera Prisma Client após instalação -``` - -## 🤝 Contribuindo - -Agradecemos contribuições da comunidade! Aqui está como você pode ajudar: - -### Para Desenvolvedores - -1. **Fork o repositório** -2. **Crie uma branch de feature** - ```bash - git checkout -b feature/amazing-feature - ``` -3. **Faça suas alterações** -4. **Commit suas alterações** - ```bash - git commit -m 'Add: amazing feature' - ``` -5. **Push para a branch** - ```bash - git push origin feature/amazing-feature - ``` -6. **Abra um Pull Request** - -### Para Usuários Finais - -- **Reportar Bugs**: Use [GitHub Issues](https://github.com/evandrodevbr/lista-compras/issues) -- **Solicitar Features**: Sugira novas funcionalidades via [GitHub Issues](https://github.com/evandrodevbr/lista-compras/issues) -- **Fornecer Feedback**: Compartilhe sua experiência e sugestões - -### Guidelines de Desenvolvimento - -- Siga o estilo de código existente -- Escreva mensagens de commit claras -- Adicione testes para novas funcionalidades -- Atualize documentação quando necessário -- Certifique-se de que todos os checks passem antes de submeter PR - -## 📄 Licença - -Este projeto está licenciado sob uma **Licença de Uso Pessoal**. - -### Permissões - -- ✅ Uso pessoal em localhost -- ✅ Inspeção de código e aprendizado -- ✅ Desenvolvimento e teste local - -### Restrições - -- ❌ Deploy público na web -- ❌ Uso comercial -- ❌ Redistribuição para terceiros -- ❌ Criação de obras derivadas para distribuição pública - -Para os termos completos da licença, consulte o arquivo [LICENSE](LICENSE). - -## 📫 Contato - -**Autor:** Evandro -**Website:** [evandro.dev.br](https://evandro.dev.br) -**GitHub:** [@evandrodevbr](https://github.com/evandrodevbr) -**Email:** evandro@evandro.dev.br - -### Links do Projeto - -- **Live Demo:** [nutriscan.evandro.dev.br](https://nutriscan.evandro.dev.br) -- **Repositório:** [github.com/evandrodevbr/lista-compras](https://github.com/evandrodevbr/lista-compras) -- **Issues:** [GitHub Issues](https://github.com/evandrodevbr/lista-compras/issues) - -## 🙏 Agradecimentos - -- **[Open Food Facts](https://world.openfoodfacts.org/)** - Pela base de dados abrangente de alimentos -- **[shadcn/ui](https://ui.shadcn.com/)** - Pela biblioteca de componentes acessíveis -- **[Next.js Team](https://nextjs.org/)** - Pelo framework React incrível -- **[Vercel](https://vercel.com/)** - Por soluções de hosting e deployment -- **[Prisma](https://www.prisma.io/)** - Pelo excelente ORM -- **Contribuidores** - Obrigado a todos que ajudam a melhorar este projeto - ---- - -
-

Desenvolvido com ❤️ por evandro.dev.br

-

Feito para usuários conscientes com a saúde e desenvolvedores ao redor do mundo

-
+## Verificação + +Não há testes automatizados neste repositório (nenhum framework de teste nas dependências) e não há CI configurada. O que existe hoje: + +- `pnpm lint` roda o ESLint (via `next lint`); +- `pnpm build` roda `prisma generate` e o `next build` com checagem de tipos; +- verificação manual de rotas com `curl`, descrita abaixo. + +Medições feitas nesta auditoria, em 14/09/2026, com Node 24.20.0 e pnpm 12.4.1: + +| Comando / requisição | Resultado | +|---|---| +| `pnpm install` | exit 0, sem precisar de flags | +| `pnpm lint` | exit 0, 6 avisos de variável não usada | +| `pnpm build` | exit 0, 13 páginas geradas, First Load JS compartilhado de 102 kB | +| `pnpm start -p 3111` | servidor no ar, respondeu 200 em 1 s | +| `GET /` | 200, 46 kB | +| `GET /sobre`, `/resultados`, `/robots.txt`, `/sitemap.xml`, `/manifest.json` | 200 | +| `GET /produto/3017620422003` | 200, produto Nutella obtido na hora na API | +| `GET /lista/audit-teste` | 200, página de lista renderizada | +| `GET /api/search?q=bis&cache_only=true` | 200, 20 produtos vindos do cache | +| `GET /api/search?q=bis&cache_only=true&page_size=5` | 200, 5 produtos | +| `GET /api/products/7622210575975?cache_only=true` | 200, `fromCache: true` | +| `GET /api/products/3017620422003` | 200, `fromAPI: true` (produto buscado e gravado no cache) | +| `GET /api/storage-stats` | 200, `totalProducts: 232`, 0,55 MB | +| `GET /api/location` | 200, `{"country":"Brazil","countryCode":"br"}` | +| `POST /api/cache/sync` com `{"products":[]}` | 200, `{"success":true,"saved":0,"failed":0}` | +| `POST /api/cache/sync` com corpo inválido | 400, `{"error":"Produtos inválidos"}` | +| `GET /api/search` sem `q` | 400, `{"error":"Query parameter is required"}` | +| `GET /api/products/123` | 400, `{"error":"Código de barras inválido"}` | +| `GET /api/search?q=x&page=0` | 400, `{"error":"Invalid page parameter"}` | + +## Estado atual e limitações + +- A busca textual depende do endpoint legado `cgi/search.pl` do Open Food Facts, que respondeu HTTP 503 durante a verificação. Na prática, buscar por nome retorna lista vazia, com a rota respondendo 200 e `count: 0`, sem derrubar a aplicação. A consulta por código de barras continua funcionando pelo endpoint `api/v2/product`. +- Sem testes automatizados e sem CI. +- O painel de filtros avançados da página de resultados guarda as escolhas na chave do cache, mas a busca enviada para `/api/search` leva apenas texto, país e paginação. Hoje o que realmente filtra a lista são os atalhos de classificação Nutri-Score e o botão de produtos sem alérgenos. +- A ordenação implementada em `lib/openFoodFactsApi.ts` cobre quatro critérios (relevância, Nutri-Score, energia e nome). As demais opções do seletor caem no caso padrão da função e não reordenam o resultado. +- O servidor grava em `data/products-cache.json`, que é versionado. Usar a aplicação altera o conteúdo do arquivo no diretório de trabalho. +- Duas lockfiles versionadas: `pnpm-lock.yaml` (usada pelo deploy) e `bun.lock`. +- Metadados, Open Graph e User-Agent apontam para `nutriscan.com.br`, domínio que não responde; a instância publicada está em `nutriscan.evandro.dev.br`, que também é a URL do `sitemap.xml` e do `robots.txt`. +- O banco SQLite versionado em `prisma/prisma/db/` vem só com a tabela `_prisma_migrations`, sem `Lista` e `Produtos`; é necessário rodar `pnpm db:push` antes de usar as listas. +- `pnpm db:migrate` existe no `package.json` mas não tem migrations para aplicar no repositório. +- O analytics é servido via proxy em `/analytics/*` para o Rybbit configurado em `NEXT_PUBLIC_RYBBIT_HOST`; sem esse serviço no ar, o script falha silenciosamente no cliente. +- A página de lista de compras renderiza para qualquer id, mesmo sem registro no banco, porque `verificarLista` retorna sucesso quando a lista não existe. + +## Documentação + +| Documento | Conteúdo | +|---|---| +| [`docs/openFoodFacts.md`](docs/openFoodFacts.md) | Anotações sobre a API do Open Food Facts | +| [`docs/logo-prompts.md`](docs/logo-prompts.md) | Prompts usados na criação das logos | +| [`docs/resedesign/`](docs/resedesign) | Referência visual do redesign | +| [`prisma/schema.prisma`](prisma/schema.prisma) | Modelo de dados das listas | + +## Licença + +Licença de uso pessoal, definida em [`LICENSE`](LICENSE): é permitido usar em máquina local, estudar o código e rodar para desenvolvimento. Não é permitido deploy público, uso comercial, redistribuição nem obras derivadas para distribuição. A instância em `nutriscan.evandro.dev.br` é do próprio autor. + +Autor: Evandro, e [@evandrodevbr](https://github.com/evandrodevbr).