Um sistema completo para receber e processar webhooks da Vercel, com armazenamento em MongoDB e expiração automática de eventos.
A complete system to receive and process Vercel webhooks, with MongoDB storage and automatic event expiration.
- Funcionalidades
- Arquitetura
- Instalação
- Configuração
- Uso
- API Endpoints
- Estrutura do Projeto
- Troubleshooting
- ✅ Recebe eventos da Vercel via webhook
- ✅ Validação de assinatura SHA1
- ✅ Suporte a todos os tipos de eventos (deployment, project, attack)
- ✅ Parsing automático do payload aninhado
- ✅ Tratamento de eventos duplicados
- ✅ MongoDB com Mongoose
- ✅ Índices otimizados para performance
- ✅ Expiração automática após 25 horas (TTL Index)
- ✅ Estrutura de dados flexível
- ✅ API de estatísticas em tempo real
- ✅ Logs detalhados de eventos
- ✅ Script de limpeza manual
- ✅ Dashboard de eventos
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Vercel │ │ Next.js API │ │ MongoDB │
│ Webhook │───▶│ Route Handler │───▶│ BuildEvents │
│ Events │ │ Validation │ │ Collection │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ Statistics │
│ API │
└─────────────────┘
- Vercel envia webhook → Evento de deployment/project/attack
- Validação de assinatura → SHA1 HMAC verification
- Parsing do payload → Extração de campos aninhados
- Salvamento no MongoDB → Com TTL de 25 horas
- Resposta de sucesso → Status 200/409 para duplicados
- Node.js 18+
- MongoDB (local ou Atlas)
- Conta na Vercel (para webhooks)
git clone <repository-url>
cd vercel-build-statusnpm installCrie um arquivo .env.local:
# MongoDB Connection String
MONGODB_URI=mongodb://localhost:27017/vercel-build-status
# Vercel Webhook Secret (obtido ao criar o webhook na Vercel)
VERCEL_WEBHOOK_SECRET=your_webhook_secret_here
# Next.js Configuration
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your_nextauth_secret_herenpm run devO servidor estará disponível em http://localhost:3000
-
Acesse o Dashboard da Vercel
- Vá para vercel.com/dashboard
- Selecione seu time/account
-
Configure o Webhook
- Settings → Webhooks
- Clique em "Create Webhook"
-
Selecione os Eventos
- ✅
deployment.created - ✅
deployment.succeeded - ✅
deployment.error - ✅
deployment.cancelled - ✅
deployment.promoted - ✅
project.created - ✅
project.removed - ✅
attack.detected
- ✅
-
Configure a URL
- Desenvolvimento:
http://localhost:3000/api/webhook - Produção:
https://seu-dominio.com/api/webhook
- Desenvolvimento:
-
Guarde o Secret
- Copie o secret fornecido pela Vercel
- Adicione ao
.env.localcomoVERCEL_WEBHOOK_SECRET
# Instalar MongoDB
brew install mongodb-community
# Iniciar MongoDB
brew services start mongodb-community
# Criar database
mongosh
use vercel-build-status- Crie uma conta em mongodb.com
- Crie um cluster gratuito
- Obtenha a connection string
- Configure no
.env.local
# Desenvolvimento
npm run dev
# Build para produção
npm run build
# Iniciar produção
npm start
# Testar webhook
npm run test:webhook
# Limpeza manual de eventos
npm run cleanup:events
# Linting
npm run lint# Teste com eventos simulados
npm run test:webhook
# Teste com evento único
npx tsx scripts/test-webhook-unique.ts# Ver estatísticas
curl http://localhost:3000/api/stats
# Ver eventos salvos
curl http://localhost:3000/api/eventsRecebe webhooks da Vercel
- Headers obrigatórios:
x-vercel-signature - Content-Type:
application/json - Respostas:
200: Evento salvo com sucesso409: Evento duplicado401: Assinatura inválida400: Payload inválido500: Erro interno
Verifica status do endpoint
{
"message": "Vercel Build Status Webhook Endpoint",
"status": "active",
"supportedEvents": [
"deployment.created",
"deployment.succeeded",
"deployment.error",
"deployment.cancelled",
"deployment.promoted",
"project.created",
"project.removed",
"attack.detected"
]
}Lista eventos salvos
Query Parameters:
page: Número da página (padrão: 1)limit: Itens por página (padrão: 20)type: Filtrar por tipo de eventostatus: Filtrar por status
Estatísticas dos eventos
{
"success": true,
"stats": {
"total": 150,
"last24h": 25,
"expiringSoon": 5,
"byType": [
{ "_id": "deployment.created", "count": 50 },
{ "_id": "deployment.succeeded", "count": 45 }
],
"byRegion": [
{ "_id": "iad1", "count": 100 },
{ "_id": "gru1", "count": 50 }
],
"recent": [...]
},
"expiration": {
"ttlHours": 25,
"description": "Eventos expiram automaticamente após 25 horas"
}
}vercel-build-status/
├── src/
│ ├── app/
│ │ ├── api/
│ │ │ ├── webhook/
│ │ │ │ └── route.ts # Webhook handler
│ │ │ ├── events/
│ │ │ │ └── route.ts # Lista eventos
│ │ │ └── stats/
│ │ │ └── route.ts # Estatísticas
│ │ ├── layout.tsx
│ │ └── page.tsx
│ ├── components/
│ │ ├── EventCard.tsx
│ │ ├── EventFilters.tsx
│ │ └── StatsCard.tsx
│ ├── lib/
│ │ └── mongodb.ts # Conexão MongoDB
│ └── models/
│ └── BuildEvent.ts # Modelo de dados
├── scripts/
│ ├── test-webhook.ts # Teste de webhook
│ └── cleanup-events.ts # Limpeza manual
├── public/
├── package.json
├── tsconfig.json
└── README.md
interface IBuildEvent {
eventId: string; // ID único do evento
type: string; // Tipo do evento (deployment.created, etc.)
createdAt: Date; // Data de criação
payload: Record<string, unknown>; // Payload completo da Vercel
region: string; // Região do evento
projectId?: string; // ID do projeto
deploymentId?: string; // ID do deployment
status?: string; // Status do evento
url?: string; // URL do deployment
meta?: { // Metadados extraídos
teamId?: string;
userId?: string;
projectName?: string;
deploymentUrl?: string;
target?: string;
alias?: string[];
framework?: string;
attackType?: string;
mitigated?: boolean;
ipAddress?: string;
userAgent?: string;
};
expiresAt: Date; // Data de expiração (25h)
}eventId: Únicotype: PerformancecreatedAt: OrdenaçãoprojectId: FiltrosdeploymentId: Filtrosstatus: Filtrosmeta.teamId: FiltrosexpiresAt: TTL (25 horas)
Causa: Secret do webhook incorreto Solução:
# Verificar se o secret está correto
echo $VERCEL_WEBHOOK_SECRET
# Reiniciar servidor com secret
VERCEL_WEBHOOK_SECRET=your_secret npm run devCausa: MongoDB não está rodando Solução:
# Verificar se MongoDB está rodando
brew services list | grep mongodb
# Iniciar MongoDB
brew services start mongodb-communityCausa: Evento já foi processado Solução: Normal, o evento foi processado com sucesso
Causa: Campos obrigatórios faltando Solução: Verificar se o payload da Vercel está correto
# Ver logs do servidor
npm run dev
# Ver eventos no MongoDB
mongosh
use vercel-build-status
db.buildevents.find().sort({createdAt: -1}).limit(10)
# Ver índices
db.buildevents.getIndexes()# Testar conexão MongoDB
npx tsx scripts/test-mongodb.ts
# Testar webhook com payload específico
npx tsx scripts/debug-webhook.ts
# Ver estatísticas detalhadas
curl http://localhost:3000/api/stats | jqO webhook valida a assinatura usando HMAC SHA1:
const signature = crypto
.createHmac('sha1', secret)
.update(payload)
.digest('hex');x-vercel-signature: Assinatura HMAC SHA1content-type:application/json
Considere implementar rate limiting para produção:
// Exemplo com express-rate-limit
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutos
max: 100 // máximo 100 requests por window
});-
Conecte o repositório
vercel --prod
-
Configure as variáveis de ambiente
MONGODB_URIVERCEL_WEBHOOK_SECRET
-
Atualize a URL do webhook
- Use a URL de produção no painel da Vercel
- Railway:
railway up - Render: Conecte via GitHub
- Heroku:
git push heroku main
- Eventos por hora: Monitorar volume
- Taxa de erro: Webhook failures
- Tempo de resposta: Performance
- Uso de disco: MongoDB storage
- Webhook retornando 5xx
- MongoDB connection failures
- Eventos não sendo salvos
- Storage > 80%
- Fork o projeto
- Crie uma branch (
git checkout -b feature/amazing-feature) - Commit suas mudanças (
git commit -m 'Add amazing feature') - Push para a branch (
git push origin feature/amazing-feature) - Abra um Pull Request
Este projeto está sob a licença MIT. Veja o arquivo LICENSE para mais detalhes.
- Issues: GitHub Issues
- Documentação: Vercel Webhooks
- Comunidade: Vercel Discord
Desenvolvido com ❤️ para a comunidade Vercel