<<<<<<< HEAD
A production-ready webhook event relay system built with Node.js, PostgreSQL, and Redis.
- β Event ingestion from internal modules
- β Webhook subscription management
- β Secure HMAC signature verification
- β Automatic retry with exponential backoff
- β Idempotency handling
- β Redis caching for performance
- β Comprehensive delivery logging
- β Rate limiting and security
- β Health monitoring endpoints
βββββββββββββββββββ
β Modulesβ
β (Jobs, Candidates)β
ββββββββββ¬βββββββββ
β Events
βΌ
βββββββββββββββββββ
β Event Service β
β (Validation) β
ββββββββββ¬βββββββββ
β
βΌ
βββββββββββββββββββ ββββββββββββ
β Redis Queue βββββββΊβPostgreSQLβ
ββββββββββ¬βββββββββ ββββββββββββ
β
βΌ
βββββββββββββββββββ
β Webhook Worker β
β (Background) β
ββββββββββ¬βββββββββ
β
βΌ
βββββββββββββββββββ
β External Systemsβ
β (HRMS, CRM) β
βββββββββββββββββββ
- Node.js 18+
- PostgreSQL 15+
- Redis 7+
- Docker (optional)
# Clone repository
git clone <repository-url>
cd -webhook-system/backend
# Install dependencies
npm install
# Copy environment file
cp .env.example .env
# Edit .env with your configuration
nano .env# Start PostgreSQL and Redis with Docker
docker-compose up -d
# Run database migrations
psql -U postgres -d _webhooks -f migrations/init.sql# Development mode
npm run dev
# Production mode
npm startThe server will start on http://localhost:3000
All API requests require authentication:
- Internal services: Use
X-Service-Tokenheader - External clients: Use
X-Api-Keyheader
Create Event (Internal only)
POST /api/events
X-Service-Token: your-service-token
Content-Type: application/json
{
"eventType": "candidate.created",
"eventName": "Candidate John Doe Created",
"payload": {
"candidateId": "123",
"name": "John Doe",
"email": "john@example.com"
},
"source": "candidates-service"
}Get Events
GET /api/events?eventType=candidate.created&limit=50&offset=0
X-Service-Token: your-service-tokenRegister Webhook
POST /api/webhooks
X-Api-Key: your-api-key
Content-Type: application/json
{
"name": "HRMS Integration",
"url": "https://hrms.example.com/webhooks",
"eventTypes": ["candidate.created", "candidate.updated"]
}Get Webhooks
GET /api/webhooks
X-Api-Key: your-api-keyUpdate Webhook
PUT /api/webhooks/:id
X-Api-Key: your-api-key
Content-Type: application/json
{
"isActive": false
}Get Delivery Logs
GET /api/webhooks/:id/deliveries
X-Api-Key: your-api-keyRetry Failed Delivery
POST /api/webhooks/:webhookId/retry/:eventId
X-Api-Key: your-api-keyGet Overview
GET /api/dashboard/overview
X-Api-Key: your-api-keyGet Recent Deliveries
GET /api/dashboard/recent-deliveries?limit=100
X-Api-Key: your-api-keyHealth Check
GET /api/dashboard/healthjob.createdjob.updatedjob.deletedcandidate.createdcandidate.updatedcandidate.status_changedinterview.scheduledinterview.completedinterview.cancelledassessment.submittedassessment.graded
When an event is delivered to your webhook, it will receive:
{
"eventId": "uuid",
"eventType": "candidate.created",
"eventName": "Candidate John Doe Created",
"data": {
"candidateId": "123",
"name": "John Doe",
"email": "john@example.com"
},
"timestamp": "2025-10-26T10:00:00.000Z"
}Content-Type: application/json
X--Signature: <hmac-sha256-signature>
X--Timestamp: <unix-timestamp>
User-Agent: -Webhook-System/1.0
To verify webhook authenticity:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
hmac.update(JSON.stringify(payload));
const expected = hmac.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}| Variable | Description | Default |
|---|---|---|
| PORT | Server port | 3000 |
| NODE_ENV | Environment | development |
| DB_HOST | PostgreSQL host | localhost |
| DB_PORT | PostgreSQL port | 5432 |
| REDIS_HOST | Redis host | localhost |
| REDIS_PORT | Redis port | 6379 |
| WEBHOOK_TIMEOUT | Request timeout (ms) | 5000 |
| WEBHOOK_MAX_RETRIES | Max retry attempts | 3 |
| WEBHOOK_RETRY_DELAY | Base retry delay (ms) | 60000 |
# Run tests
npm test
# Run with coverage
npm run test:coveragecurl http://localhost:3000/healthcurl -H "X-Api-Key: your-key" http://localhost:3000/api/dashboard/metrics# Build image
docker build -t -webhook-system .
# Run container
docker run -p 3000:3000 --env-file .env -webhook-system- Set strong
API_SECRET_KEYandHMAC_SECRET - Configure proper CORS origins
- Set up SSL/TLS certificates
- Enable production logging
- Configure database backups
- Set up monitoring and alerts
- Configure rate limiting
- Review security headers
Database connection failed
- Check PostgreSQL is running
- Verify credentials in .env
- Ensure database exists
Redis connection failed
- Check Redis is running
- Verify REDIS_HOST and REDIS_PORT
Webhooks not delivering
- Check webhook worker is running
- Verify target URL is accessible
- Check delivery logs for errors
MIT
For issues and questions, please contact vikranthbolleddula@gmail.com
A modern React dashboard for managing and monitoring the Webhook Event Relay System.
- Dashboard Overview - Real-time statistics and system health monitoring
- Webhook Management - Create, update, and delete webhook subscriptions
- Event Tracking - View all system events with filtering and search
- Delivery Monitoring - Track delivery status, retries, and failures
- Statistics - Detailed analytics for each webhook
- Responsive Design - Works on desktop, tablet, and mobile
- React 18 - UI library
- Vite - Build tool and dev server
- React Router - Client-side routing
- TailwindCSS - Utility-first CSS framework
- ShadCN UI - Modern component library
- Axios - HTTP client
- Recharts - Chart library
- Lucide React - Icon library
frontend/
βββ public/
βββ src/
β βββ components/
β β βββ ui/ # ShadCN UI components
β β β βββ button.jsx
β β β βββ card.jsx
β β β βββ badge.jsx
β β β βββ input.jsx
β β β βββ dialog.jsx
β β β βββ tabs.jsx
β β β βββ switch.jsx
β β β βββ label.jsx
β β βββ Layout.jsx # Main layout with sidebar
β β βββ CreateWebhookDialog.jsx
β β βββ WebhookDetailsDialog.jsx
β βββ pages/
β β βββ Dashboard.jsx # Overview page
β β βββ Webhooks.jsx # Webhook management
β β βββ Events.jsx # Events listing
β βββ services/
β β βββ api.js # API client and endpoints
β βββ lib/
β β βββ utils.js # Utility functions
β βββ App.jsx # Main app component
β βββ main.jsx # Entry point
β βββ index.css # Global styles
βββ .env # Environment variables
βββ .env.example # Environment template
βββ package.json
βββ vite.config.js
βββ tailwind.config.js
βββ postcss.config.js
- Node.js 18+
- Backend server running on http://localhost:3000
# Navigate to frontend directory
cd frontend
# Install dependencies
npm install
# Create environment file
cp .env.example .env
# Start development server
npm run devThe dashboard will be available at http://localhost:5173
Create a .env file:
VITE_API_URL=http://localhost:3000
VITE_API_KEY=-secret-key-2024-change-in-production# Development server
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Lint code
npm run lint- System Overview: Total deliveries, success rate, active webhooks
- Real-time Updates: Auto-refresh every 30 seconds
- Recent Deliveries: Latest webhook delivery attempts
- Health Status: System health indicator
- Register Webhooks: Create new webhook subscriptions
- Event Selection: Choose which events to subscribe to
- Toggle Status: Enable/disable webhooks
- View Details: Delivery history and statistics
- Delete Webhooks: Remove subscriptions
- Event Listing: View all system events
- Search: Filter events by name or type
- Event Types Filter: Quick filter by event type
- Event Details: View full event payload
- Refresh: Manual data refresh
import { Button } from '@/components/ui/button';
<Button variant="default">Click me</Button>
<Button variant="outline">Outline</Button>
<Button variant="destructive">Delete</Button>import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
</CardHeader>
<CardContent>Content here</CardContent>
</Card>import { Badge } from '@/components/ui/badge';
<Badge variant="success">Active</Badge>
<Badge variant="error">Failed</Badge>import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog';
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent>
<DialogTitle>Title</DialogTitle>
Content here
</DialogContent>
</Dialog>The frontend communicates with the backend through Axios:
// Example: Get all webhooks
import { webhooksAPI } from '@/services/api';
const response = await webhooksAPI.getAll();
const webhooks = response.data.data;
// Example: Create webhook
const newWebhook = await webhooksAPI.create({
name: 'My Webhook',
url: 'https://api.example.com/webhook',
eventTypes: ['candidate.created']
});Webhooks
webhooksAPI.getAll(params)webhooksAPI.getById(id)webhooksAPI.create(data)webhooksAPI.update(id, data)webhooksAPI.delete(id)webhooksAPI.toggle(id, isActive)webhooksAPI.getDeliveries(id, params)webhooksAPI.getStats(id)webhooksAPI.retry(webhookId, eventId)
Events
eventsAPI.getAll(params)eventsAPI.getById(id)eventsAPI.create(data)eventsAPI.getStats()
Dashboard
dashboardAPI.getOverview()dashboardAPI.getRecentDeliveries(limit)dashboardAPI.getHealth()dashboardAPI.getMetrics()
Colors are defined in src/index.css using CSS variables:
:root {
--primary: 221.2 83.2% 53.3%;
--secondary: 210 40% 96.1%;
--destructive: 0 84.2% 60.2%;
/* ... more colors */
}The system supports dark mode via the .dark class:
// Toggle dark mode
document.documentElement.classList.toggle('dark');# Build for production
npm run build
# Preview build
npm run preview
# Deploy dist/ folder to your hosting serviceThe build creates optimized files in dist/:
- Minified JavaScript
- Optimized CSS
- Asset optimization
- Code splitting
The dashboard is fully responsive:
- Desktop (1024px+): Full sidebar navigation
- Tablet (768px-1023px): Collapsible sidebar
- Mobile (<768px): Bottom navigation
# Add testing library (optional)
npm install -D @testing-library/react @testing-library/jest-dom vitest
# Run tests
npm run test- API keys stored in environment variables
- HTTPS-only webhook URLs enforced
- CORS handled by backend
- No sensitive data in localStorage
Ensure backend CORS is configured to allow http://localhost:5173
Check that:
- Backend is running on http://localhost:3000
VITE_API_URLin.envis correctVITE_API_KEYmatches backend configuration
Clear cache and restart dev server:
rm -rf node_modules .vite
npm install
npm run devUpdate dependencies:
npm update
npm run build- Lazy loading for routes
- Optimized bundle size (~150KB gzipped)
- Code splitting by route
- Efficient re-renders with React hooks
Currently using React hooks (useState, useEffect). For larger apps, consider:
- React Context for global state
- Zustand for simple state management
- React Query for API data caching
- Create feature branch
- Make changes
- Test thoroughly
- Submit pull request
MIT
- Start Backend:
cd backend && npm run dev - Start Frontend:
cd frontend && npm run dev - Open Browser: http://localhost:5173
- Register Webhook: Click "Register Webhook" button
- Create Event: Use API or backend to create test event
- Monitor: Watch deliveries in real-time
1b24054 (Initial commit)