Sistema completo de gestão de estoque do Lamar Burger RJ com dois canais de acesso:
- Bot Telegram (@LamarBurguerRJBot) — cadastro por texto livre, áudio e foto diretamente pelo celular
- Interface Web (PWA) — painel administrativo instalável como app, com dashboard, gráficos, CRUD e entrada por voz/imagem
Todo o armazenamento é feito no Google Sheets. A IA roda via Groq (Whisper + Llama). Deploy na Vercel com Vercel Analytics para monitoramento de page views.
📖 Tutorial do bot: TUTORIAL.md
🗺️ Referência de rotas: ROUTES.md
┌─────────────────────────────────────┐
│ Google Sheets (DB) │
└────────────┬────────────────────────┘
│
┌──────────────────┼──────────────────────┐
▼ ▼ ▼
Telegram Bot API /api/web/* /api/cron/alerts
/api/webhook (REST + Auth) (Vercel Cron)
│ │
▼ ▼
handler.ts AppLayout (PWA)
commands.ts Dashboard / Estoque
aiParser.ts Produtos / Relatórios
│
Groq API (Whisper + Llama + Vision)
- Conta na Vercel
- Bot no Telegram via @BotFather
- Chave de API do Groq (plano gratuito disponível)
- Planilha no Google Sheets com Service Account
- (Opcional) OAuth Client ID do Google Cloud para login via Google na web
git clone <url-do-repositorio> lamar-bot
cd lamar-bot
npm install- Acesse o Google Cloud Console
- Crie um projeto → ative a Google Sheets API
- Vá em Credenciais → Criar credenciais → Conta de serviço
- Baixe o JSON da conta de serviço
- Crie uma planilha no Google Sheets (as abas
ProdutoseEstadosão criadas automaticamente) - Compartilhe com o e-mail da service account (permissão de Editor)
- Copie o ID da planilha da URL:
https://docs.google.com/spreadsheets/d/<GOOGLE_SHEET_ID>/edit
cp .env.example .env.localPreencha todas as variáveis (veja a seção Variáveis de ambiente abaixo).
Para gerar segredos:
openssl rand -hex 32
Para minificar o JSON da service account:cat google-service-account.json | jq -c .
npx vercel --prodOu conecte o repositório no dashboard da Vercel e configure as variáveis de ambiente lá.
curl -X POST "https://api.telegram.org/bot<TOKEN>/setWebhook" \
-d "url=https://seu-projeto.vercel.app/api/webhook" \
-d "secret_token=<TELEGRAM_WEBHOOK_SECRET>"Verifique:
curl "https://api.telegram.org/bot<TOKEN>/getWebhookInfo"- No Google Cloud Console, vá em APIs & Services → Credentials
- Crie um OAuth 2.0 Client ID do tipo Web application
- Em Authorized JavaScript origins, adicione
https://seu-projeto.vercel.app - Copie o Client ID e adicione ao
.env.local:GOOGLE_CLIENT_ID=<client_id>.apps.googleusercontent.com NEXT_PUBLIC_GOOGLE_CLIENT_ID=<client_id>.apps.googleusercontent.com
Acesse https://seu-projeto.vercel.app/login no navegador ou celular.
Para instalar como app: no iOS/Android, use "Adicionar à tela inicial"; no desktop Chrome/Edge, clique no ícone de instalar na barra de endereços.
| Página | URL | Descrição |
|---|---|---|
| Login | /login |
Login com senha ou Google |
| Dashboard | /app/dashboard |
Métricas e gráficos do estoque |
| Estoque | /app/estoque |
Tabela completa e ordenável |
| Produtos | /app/produtos |
CRUD + entrada por voz e imagem |
| Relatórios | /app/relatorios |
Análises com filtro de período |
O Vercel Cron dispara /api/cron/alerts todo dia às 09:00 BRT (12:00 UTC).
Cada usuário recebe alerta sobre produtos vencendo em breve. O admin recebe um resumo geral.
Configurado em
vercel.json. Ajuste o horário conforme necessário (formato UTC).
nvm use 20 # Node.js 20+ necessário
npm run dev # inicia em http://localhost:3000
npm run lint
npm run buildyarn test # todos os testes (509 testes)
yarn test:unit # apenas testes unitários (404 testes)
yarn test:integration # apenas testes de integração (105 testes)
yarn test:coverage # todos com relatório de cobertura + badges SVGO pipeline de CI roda automaticamente no GitHub a cada push. Consulte docs/ci-pipeline.md para detalhes dos jobs e docs/tutorial-setup-ci-pipeline.md para o guia de configuração.
Para testar o webhook localmente, use ngrok:
npx next dev ngrok http 3000 # registre a URL do ngrok no setWebhook
lamar-bot/
├── vercel.json # Cron jobs
├── next.config.ts
├── .env.example
├── docs/TUTORIAL.md # Manual do bot Telegram
├── docs/ROUTES.md # Referência de todas as rotas
├── public/
│ ├── manifest.json # PWA manifest
│ ├── sw.js # Service Worker
│ └── icons/ # Ícones PWA
└── src/
├── middleware.ts # Proteção de rotas (Edge)
├── app/
│ ├── layout.tsx # Root layout (meta PWA + Vercel Analytics)
│ ├── page.tsx # Status page
│ ├── login/page.tsx # Tela de login
│ ├── app/
│ │ ├── layout.tsx # Layout com sidebar
│ │ ├── page.tsx # Redirect → dashboard
│ │ ├── dashboard/page.tsx # Dashboard com gráficos
│ │ ├── estoque/page.tsx # Tabela de inventário
│ │ ├── produtos/page.tsx # CRUD + IA
│ │ └── relatorios/page.tsx # Relatórios
│ └── api/
│ ├── auth/
│ │ ├── login/route.ts # POST login senha
│ │ ├── google/route.ts # POST login Google
│ │ ├── logout/route.ts # POST logout
│ │ └── me/route.ts # GET usuário atual
│ ├── web/
│ │ ├── produtos/route.ts # GET + POST produtos
│ │ ├── produtos/[rowIndex]/route.ts # PUT + DELETE produto
│ │ └── ai/parse/route.ts # POST parse áudio/imagem
│ ├── webhook/route.ts # POST Telegram webhook
│ └── cron/alerts/route.ts # GET alertas de vencimento
├── components/
│ ├── AppLayout.tsx # Sidebar + hamburger menu
│ └── InstallBanner.tsx # Banner de instalação PWA
└── lib/
├── auth.ts # JWT sign/verify
├── sheets.ts # Google Sheets (produtos + estado)
├── aiParser.ts # IA: texto, Whisper, Vision
├── telegram.ts # Telegram Bot API
├── handler.ts # Lógica central do bot
└── commands.ts # Comandos e menu
| Variável | Obrigatório | Descrição |
|---|---|---|
TELEGRAM_TOKEN |
✅ | Token do bot (BotFather) |
TELEGRAM_WEBHOOK_SECRET |
✅ | Segredo do webhook — protege /api/webhook. Gere com openssl rand -hex 32 |
GROQ_API_KEY |
✅ | Chave Groq para IA — console.groq.com |
GOOGLE_SHEET_ID |
✅ | ID da planilha Google Sheets |
GOOGLE_SERVICE_ACCOUNT_JSON |
✅ | JSON minificado da service account |
ADMIN_CHAT_ID |
✅ | Chat ID do admin para alertas diários |
CRON_SECRET |
✅ | Bearer token para /api/cron/alerts |
WEBAPP_USERNAME |
✅ | Usuário do login web |
WEBAPP_PASSWORD |
✅ | Senha do login web |
JWT_SECRET |
✅ | Segredo para assinar os JWTs da web. Gere com openssl rand -hex 32 |
GOOGLE_CLIENT_ID |
— | Client ID do OAuth Google (backend — verifica o token) |
NEXT_PUBLIC_GOOGLE_CLIENT_ID |
— | Mesmo valor, exposto ao browser (renderiza o botão Google) |
NEXT_PUBLIC_GOOGLE_SHEET_ID |
— | ID da planilha, exposto ao browser (link direto na sidebar) |
Telegram Bot API
│
▼
/api/webhook (Next.js Route Handler)
│
▼
handler.ts ← roteamento de mensagens
│
┌────┴─────────────┐
▼ ▼
aiParser.ts commands.ts
(texto/áudio/foto) (estoque, vencendo, relatório...)
│
▼
sheets.ts ← Google Sheets (produtos + estado)
/api/cron/alerts ← alertas diários via Vercel Cron
- Conta na Vercel (Hobby ou Pro)
- Bot criado no Telegram via @BotFather
- Chave de API do Groq (gratuita)
- Planilha no Google Sheets com Service Account
git clone <url-do-repositorio> lamar-bot
cd lamar-bot
npm install- Acesse o Google Cloud Console
- Crie um projeto → ative a Google Sheets API
- Vá em Credenciais → Criar credenciais → Conta de serviço
- Baixe o JSON da conta de serviço
- Crie uma planilha no Google Sheets (as abas
ProdutoseEstadosão criadas automaticamente pelo bot) - Compartilhe a planilha com o e-mail da conta de serviço (permissão de Editor)
- Copie o ID da planilha da URL:
https://docs.google.com/spreadsheets/d/<GOOGLE_SHEET_ID>/edit
cp .env.example .env.localPreencha as variáveis:
TELEGRAM_TOKEN=1234567890:AAFxxxxxxxxxxxxxxxxxxxxxxxx
TELEGRAM_WEBHOOK_SECRET=<gerado com openssl rand -hex 32>
GROQ_API_KEY=gsk_xxxxxxxxxxxxxxxxxxxxxxxx
GOOGLE_SHEET_ID=1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms
GOOGLE_SERVICE_ACCOUNT_JSON={"type":"service_account","project_id":"..."}
ADMIN_CHAT_ID=123456789
CRON_SECRET=um_segredo_aleatorio_aquiPara gerar um segredo seguro:
openssl rand -hex 32
Dica: Para
GOOGLE_SERVICE_ACCOUNT_JSON, minifique o JSON em uma única linha (sem quebras).
Use:cat google-service-account.json | jq -c .
npx vercel --prodOu conecte o repositório diretamente no dashboard da Vercel e configure as variáveis de ambiente lá.
Após o deploy, configure o webhook com o secret token para proteger o endpoint:
curl -X POST "https://api.telegram.org/bot<SEU_TOKEN>/setWebhook" \
-d "url=https://seu-projeto.vercel.app/api/webhook" \
-d "secret_token=<VALOR_DE_TELEGRAM_WEBHOOK_SECRET>"Verifique:
curl "https://api.telegram.org/bot<SEU_TOKEN>/getWebhookInfo"O
secret_tokenfaz com que o Telegram envie o headerX-Telegram-Bot-Api-Secret-Tokenem cada update. O bot rejeita requests sem esse header com403 Forbidden.
Para desenvolvimento local, use o ngrok:
npx next dev # porta 3000 ngrok http 3000 # exponha e use a URL no setWebhook
Na primeira mensagem (ou sempre que não houver interação em andamento), o bot exibe o menu principal:
🍔 Lamar Burger RJ — O que deseja fazer?
[ 📝 1. Cadastrar produto ]
[ 📦 2. Estoque ]
[ ⚠️ 3. Vencendo ] [ 📋 4. Produtos vencendo ]
[ 📊 5. Relatório ] [ 📊 6. Relatório hoje ]
[ ✏️ 7. Editar produto ] [ 🗑️ 8. Deletar produto ]
[ 🗂️ 9. Abrir planilha ]
Ao clicar em 1. Cadastrar produto, um sub-menu aparece com três opções:
[ 📋 Preencher formulário ]
[ 🎤 Enviar áudio ]
[ 📷 Enviar imagem / foto ]
[ ⬅️ Voltar ao menu ]
O bot envia um formulário para preencher. Você também pode simplesmente escrever livremente — a IA interpreta:
comprei 20 pães brioche da Wickbold por 12,90, vencem dia 10/04
Após escolher "Enviar áudio", envie uma mensagem de voz descrevendo o produto. O bot transcreve com Whisper (Groq) e extrai os dados automaticamente.
Após escolher "Enviar imagem", envie a foto do produto ou nota fiscal. O bot usa visão computacional para extrair todos os itens de uma vez.
Após salvar, o bot pergunta:
✅ Produto cadastrado com sucesso!
• Pão Brioche
Deseja cadastrar outro produto?
[ Sim ] [ Não ]
Clique em 7. Editar produto ou use o comando de voz:
editar pão brioche
alterar coca-cola
O bot lista seus produtos como botões. Ao selecionar, exibe os dados atuais e um teclado com os campos editáveis (Nome, Valor, Quantidade, Peso, Marca, Data Compra, Data Vencimento). Depois é só digitar o novo valor.
Clique em 8. Deletar produto ou use o comando de voz:
deletar mortadela
apagar pão
excluir coca-cola
remover frango
O bot lista seus produtos, pede confirmação e remove a linha da planilha.
Se mais de um produto corresponder ao nome, o bot apresenta uma lista para escolha.
| Comando | O que faz |
|---|---|
estoque |
Lista todos os produtos com cartões formatados + botão "Ver como tabela" |
vencendo |
Produtos que vencem nos próximos 3 dias |
produto pão brioche |
Busca e exibe detalhes de um produto pelo nome |
relatório |
Resumo geral: total, valor em estoque, itens vencendo, nº de usuários |
relatório hoje |
Somente produtos cadastrados hoje + valor + itens vencendo |
editar <nome> |
Abre o menu de edição direto pelo nome |
deletar <nome> / apagar <nome> |
Abre a confirmação de exclusão pelo nome |
Todos os comandos de menu também funcionam digitados como texto.
O Vercel Cron dispara /api/cron/alerts todo dia às 09:00 BRT (12:00 UTC).
Cada usuário recebe uma notificação sobre seus produtos prestes a vencer.
O admin (ADMIN_CHAT_ID) recebe um resumo geral.
A configuração está em
vercel.json. Ajuste o horário conforme necessário (formato UTC).
npm run dev # inicia em http://localhost:3000
npm run lint # verifica ESLint
npm run format # formata com Prettier
npm run build # build de produçãolamar-bot/
├── vercel.json # Cron jobs
├── next.config.ts
├── tsconfig.json
├── eslint.config.mjs
├── .prettierrc
├── .env.example
└── src/
├── app/
│ ├── page.tsx # Status page
│ ├── layout.tsx
│ └── api/
│ ├── webhook/route.ts # Recebe updates do Telegram
│ └── cron/alerts/route.ts # Alerta diário de vencimento
└── lib/
├── telegram.ts # Telegram Bot API
├── sheets.ts # Google Sheets (produtos + estado)
├── aiParser.ts # IA: texto, áudio (Whisper), foto (Vision)
├── handler.ts # Lógica central do bot
└── commands.ts # Comandos e menu principal
| Variável | Obrigatório | Descrição |
|---|---|---|
TELEGRAM_TOKEN |
✅ | Token do bot (BotFather) |
TELEGRAM_WEBHOOK_SECRET |
✅ | Segredo do webhook — protege /api/webhook de requests forjados. Gere com openssl rand -hex 32 e passe no setWebhook |
GROQ_API_KEY |
✅ | Chave da API Groq — obtenha em console.groq.com (plano gratuito disponível) |
GOOGLE_SHEET_ID |
✅ | ID da planilha Google Sheets |
GOOGLE_SERVICE_ACCOUNT_JSON |
✅ | JSON minificado da service account (sem quebras de linha) |
ADMIN_CHAT_ID |
✅ | Chat ID numérico do admin para alertas diários |
CRON_SECRET |
✅ | Segredo Bearer para proteger /api/cron/alerts |
- O
maxDuration = 60nos routes requer o plano Pro. No plano Hobby o limite é 10 segundos. - Processamento de áudio/imagem pode ultrapassar 10s — considere o Pro para uso em produção.
- Vercel Cron jobs também requerem o plano Pro para agendamentos personalizados.
Bot de Telegram para cadastro e gestão de estoque do Lamar Burger RJ, com suporte a mensagens de texto livre, áudio e foto de nota fiscal. Tudo interpretado por IA e salvo automaticamente no banco de dados (e opcionalmente no Google Sheets).
- Recebe mensagens de texto livre, áudio e foto de nota fiscal
- Usa IA (OpenAI) para extrair automaticamente os dados do produto
- Salva no PostgreSQL e opcionalmente no Google Sheets
- Responde com botões interativos Sim / Não
- Aceita comandos inteligentes como
estoque,vencendo,relatório - Alerta diário às 09h sobre produtos prestes a vencer
Telegram Bot API
│
▼
Webhook (Express) ← responde em <100ms
│
▼
Fila (BullMQ + Redis) ← desacopla recebimento do processamento
│
▼
Worker (Node.js)
│
┌────┴────────────────┐
▼ ▼
IA Parser Comandos
(texto/áudio/foto) (estoque, vencendo...)
│
┌────┴────┐
▼ ▼
PostgreSQL Google Sheets
- Docker e Docker Compose instalados
- Bot criado no Telegram via @BotFather
- Chave de API da OpenAI
- (Opcional) Planilha no Google Sheets com Service Account
git clone <url-do-repositorio> lamar-bot
cd lamar-botcp .env.example .envAbra o .env e preencha cada variável:
PORT=3000
# --- Telegram ---
TELEGRAM_TOKEN=1234567890:AAFxxxxxxxxxxxxxxxxxxxxxxxx # Token do BotFather
# --- Groq ---
GROQ_API_KEY=gsk_xxxxxxxxxxxxxxxxxxxxxxxx
# --- Google Sheets (opcional) ---
GOOGLE_SHEET_ID=1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms
# --- PostgreSQL ---
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=lamar
POSTGRES_USER=lamar
POSTGRES_PASSWORD=SenhaForteAqui123
# --- Redis ---
REDIS_HOST=redis
REDIS_PORT=6379
# --- Admin (recebe alertas diários) ---
ADMIN_CHAT_ID=123456789Dica: O
TELEGRAM_TOKENé fornecido pelo @BotFather ao criar o bot. OADMIN_CHAT_IDé o ID numérico do seu usuário no Telegram (você pode obtê-lo enviando uma mensagem para @userinfobot).
- Acesse t.me/BotFather e crie um novo bot com
/newbot - Copie o token gerado e cole em
TELEGRAM_TOKENno.env - Após subir os containers, registre o webhook uma vez:
curl -X POST "https://api.telegram.org/bot<SEU_TOKEN>/setWebhook" \ -d "url=https://seu-dominio.com/webhook"
- Verifique se o webhook foi registrado:
curl "https://api.telegram.org/bot<SEU_TOKEN>/getWebhookInfo"
Para desenvolvimento local, use o ngrok para expor a porta 3000:
ngrok http 3000 # Use a URL gerada (ex: https://abc123.ngrok.io) no setWebhook acima
- Acesse o Google Cloud Console
- Crie um projeto → ative a Google Sheets API
- Vá em Credenciais → Criar credenciais → Conta de serviço
- Baixe o JSON da conta de serviço e salve como
google-service-account.jsonna raiz do projeto - Abra sua planilha no Google Sheets e compartilhe com o e-mail da conta de serviço (com permissão de Editor)
- Copie o ID da planilha da URL:
https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms/edit ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ este é o GOOGLE_SHEET_ID - Salve o arquivo como
google-service-account.jsonna raiz do projeto — o scriptcompose.shdetecta automaticamente e monta o volume.
./compose.sh up --build -dVerifique se está tudo rodando:
./compose.sh psSaída esperada:
NAME STATUS
lamar-bot-api-1 Up (healthy)
lamar-bot-worker-1 Up
lamar-bot-redis-1 Up
lamar-bot-postgres-1 Up (healthy)
Veja os logs em tempo real:
./compose.sh logs -fAo receber qualquer mensagem, o bot envia o formulário:
Lamar Burger Rj
🤖 Oi, eu sou o LAMAR, e vou te ajudar no cadastro de produtos...
🌐 NOME:
💵 VALOR:
🥡 QUANTIDADE:
⚖️ PESO:
💬 MARCA?:
🗓️ DATA DA COMPRA:
🗓️ DATA DE VENCIMENTO:
Você pode responder preenchendo o formulário:
🌐 NOME: Pão Brioche
💵 VALOR: 12.90
🥡 QUANTIDADE: 20
💬 MARCA?: Wickbold
🗓️ DATA DE VENCIMENTO: 10/04/2026
Você também pode escrever naturalmente — a IA interpreta:
comprei 20 pães brioche da Wickbold por 12,90 reais, vencem dia 10/04
10 ketchup heinz pequeño, 8 reais cada, vence 20/05
Basta enviar um áudio falando o produto:
"Comprei vinte pães brioche por doze reais e noventa centavos, vence dia dez de abril"
O bot transcreve com o Whisper da OpenAI e extrai os dados automaticamente.
Tire uma foto da nota fiscal ou do produto e envie. O bot usa visão computacional para extrair todos os itens da imagem e cadastrá-los de uma vez.
Após salvar, o bot pergunta:
✅ Produto cadastrado com sucesso!
• Pão Brioche
Deseja cadastrar outro produto?
[ Sim ] [ Não ]
- Sim → exibe o formulário novamente
- Não → encerra a conversa
Envie qualquer um dos comandos abaixo a qualquer momento:
| Comando | O que faz |
|---|---|
estoque |
Lista todos os seus produtos cadastrados |
vencendo ou produtos vencendo |
Mostra produtos que vencem nos próximos 3 dias |
produto pão brioche |
Busca um produto específico pelo nome |
relatório ou relatorio hoje |
Resumo do dia: total cadastrado, valor e itens vencendo |
Exemplo de resposta do estoque:
📦 Estoque atual
• Batata: 10 un
• Ketchup Heinz: 15 un
• Pão Brioche: 20 un
Exemplo de resposta do vencendo:
⚠️ Produtos vencendo em breve
• Pão Brioche — vence 10/04/2026
• Queijo Cheddar — vence 11/04/2026
Exemplo de resposta do relatório:
📊 Relatório de hoje
Produtos cadastrados: 8
Valor total no estoque: R$ 230.50
Itens vencendo em breve: 2
Todo dia às 09:00 o bot envia automaticamente para o chat do admin (configurado em ADMIN_CHAT_ID) e para cada usuário que tenha produtos cadastrados:
⚠️ Alerta diário — produtos vencendo:
• Pão Brioche — vence 10/04/2026
• Batata Palha — vence 11/04/2026
# Subir os serviços
./compose.sh up -d
# Parar os serviços
./compose.sh down
# Ver logs de todos os serviços
./compose.sh logs -f
# Ver logs só da API
./compose.sh logs -f api
# Ver logs só do worker
./compose.sh logs -f worker
# Rebuild após mudanças no código
./compose.sh up --build -d
# Acessar o banco de dados
./compose.sh exec postgres psql -U lamar -d lamarlamar-bot/
├── Dockerfile
├── docker-compose.yml
├── package.json
├── .env.example
├── .gitignore
└── src/
├── server.js # Webhook HTTP — recebe mensagens e coloca na fila
├── worker.js # Processa as mensagens da fila (concurrency 5)
├── queue.js # Fila BullMQ + Redis
├── handler.js # Lógica central do bot (roteamento de mensagens)
├── telegram.js # Envio de mensagens e download de mídia via Telegram Bot API
├── aiParser.js # Parser com IA: texto, áudio (Whisper), foto (Vision)
├── sheets.js # Integração Google Sheets (opcional)
├── db.js # PostgreSQL + migração automática
├── state.js # Estado da conversa no Redis (TTL 1h)
├── commands.js # Comandos inteligentes (estoque, vencendo, relatório)
└── alerts.js # Cron de alerta diário de vencimento
Use sempre a API oficial do Telegram. Nunca compartilhe o TELEGRAM_TOKEN publicamente.