A Node.js application that handles Frontegg webhooks for user events, integrating with HubSpot and Slack.
- Handles Frontegg user events (signup, activation)
- Creates HubSpot contacts for new users
- Sends Slack notifications for user activities
- Assigns users to tenants with appropriate roles
- Secure webhook authentication
- Node.js (v14 or higher)
- npm or yarn
- Vercel CLI (
npm i -g vercel) - Frontegg account and API credentials
- HubSpot API key (optional)
- Slack webhook URL (optional)
- Postman (for testing)
The application uses different environment files for different environments:
- Clone the repository:
git clone <repository-url>
cd frontegg- Install dependencies:
npm install- Start the Vercel development server:
vercel devThe server will start on http://localhost:3000 by default.
The project uses Vitest for testing. Tests are located in the api/__tests__ directory.
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverageapi/__tests__/webhook.test.js- Webhook handler testsapi/__tests__/utils/- Utility class testsapi/__tests__/services/- Service class tests
The tests use a dedicated test environment configuration:
- Environment variables are loaded from
.env.test - All external API calls are mocked to use local mock endpoints
- Console methods are mocked to prevent test output pollution
- The test environment is automatically set when running tests
The tests use Vitest's mocking capabilities to mock external API calls:
- Frontegg API calls are mocked in
api/__tests__/utils/fronteggUtil.test.js - HubSpot API calls are mocked in
api/__tests__/services/hubspotService.test.js - Slack API calls are mocked in
api/__tests__/services/slackService.test.js
Example of mocking an API call:
import { vi } from 'vitest';
import axios from 'axios';
vi.mock('axios');
axios.post.mockResolvedValue({ data: { accessToken: 'mock-token' } });POST /api/webhook
Headers:
x-vercel-protection-bypass: VERCEL_AUTOMATION_BYPASS_SECRETx-webhook-secret: Webhook authentication token
Body:
{
"user": {
"id": "test-user-id",
"name": "Test User",
"email": "test@causely.io",
"tenantIds": [
"test-tenant-id"
],
"tenantId": "test-tenant-id"
},
"eventContext": {
"vendorId": "test-Vendor-id",
"tenantId": "test-tenant-id",
"userId": "test-user-id",
"applicationId": "test-application-id"
},
"eventKey": "frontegg.user.signedUp"
}The application uses a centralized error handling system (ErrorUtil) that provides consistent error responses:
- 400 Bad Request
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
- 405 Method Not Allowed
- 500 Internal Server Error
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request