Multi-tenant SaaS that automates revenue operations for HubSpot: OAuth, signature-validated webhooks, priority lead routing, lifecycle enforcement, drift audits, and safe de-duplication.
NestJS API · Next.js admin · worker + scheduled audits · Terraform-deployed on GCP · ~$15–25/mo to run
A multi-tenant SaaS that automates RevOps workflows for HubSpot users:
- OAuth Integration: Connect HubSpot via OAuth, with encrypted token storage and auto-refresh
- Webhook Processing: Receive HubSpot webhooks with v3 signature validation, ACK fast, queue work
- Routing Rules: Priority-based lead routing with SLA task creation and escalations
- Lifecycle Contract: Define stage transitions and required fields, detect violations
- Drift Monitoring: Scheduled audits surface data quality issues
- Duplicates Remediation: Safe merge workflow with approval and audit logs
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ HubSpot Portal │────▶│ Cloud Run: API │────▶│ Cloud Tasks │
│ │ │ (Webhooks) │ │ (Event Queue) │
└─────────────────┘ └──────────────────┘ └────────┬────────┘
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Admin Dashboard│────▶│ Cloud SQL │◀────│ Cloud Run: │
│ (Next.js) │ │ (Postgres) │ │ Worker │
└─────────────────┘ └──────────────────┘ └─────────────────┘
▲
│
┌────────┴────────┐
│ Cloud Scheduler │
│ (Audits) │
└─────────────────┘
- Node.js 20+
- pnpm 9+
- Docker Desktop
# 1. Clone and install
git clone <repo>
cd revops-autopilot
pnpm install
# 2. Start infrastructure (Postgres + Redis)
docker compose up -d
# 3. Configure environment
# Create .env files in apps/api, apps/worker, apps/web
# See each directory for .env.example templates
# 4. Run migrations and seed
pnpm db:migrate
pnpm db:seed
# 5. Start development servers
pnpm devThis starts:
- API at http://localhost:8080
- Worker at http://localhost:8090
- Web Dashboard at http://localhost:3000
# Expose API for HubSpot webhooks
ngrok http 8080
# Set your HubSpot app webhook URL to:
# https://<ngrok-id>.ngrok.io/webhooks/hubspot├── apps/
│ ├── api/ # NestJS API + OAuth + Webhook receiver
│ │ ├── prisma/ # Database schema + migrations
│ │ └── src/
│ │ └── modules/
│ │ ├── hubspot/ # OAuth + HubSpot client
│ │ ├── webhooks/ # Webhook receiver + v3 validation
│ │ ├── routing/ # Routing rules CRUD + test
│ │ ├── lifecycle/ # Lifecycle contract CRUD
│ │ ├── drift/ # Drift alerts management
│ │ ├── remediation/ # Remediation jobs + approval
│ │ └── queue/ # BullMQ (local) / Cloud Tasks (GCP)
│ │
│ ├── worker/ # Event processor + scheduled audits
│ │ └── src/
│ │ └── services/
│ │ ├── idempotency.ts # Prevent duplicate writes
│ │ └── routing-evaluator.ts # Rule evaluation engine
│ │
│ └── web/ # Next.js admin dashboard
│ └── app/
│ ├── connect/ # HubSpot connection status
│ ├── routing/ # Routing rules UI
│ ├── contract/ # Lifecycle contract editor
│ ├── drift/ # Drift monitor dashboard
│ └── remediation/ # Remediation queue
│
├── packages/
│ └── shared/ # Shared types, schemas, HubSpot client
│
└── infra/
└── gcp/
└── terraform/ # Cloud Run, Cloud Tasks, Cloud SQL, IAM
GET /integrations/hubspot/connect- Redirect to HubSpot OAuthGET /integrations/hubspot/callback- OAuth callbackGET /api/integrations/hubspot/status- Connection status
POST /webhooks/hubspot- Receive HubSpot webhooks (validates signature v3)
GET /api/routing-rules- List rules by priorityPOST /api/routing-rules- Create rulePUT /api/routing-rules/:id- Update ruleDELETE /api/routing-rules/:id- Delete rulePOST /api/routing-rules/test- Test rules against a contact
GET /api/lifecycle-contract- Get contractPUT /api/lifecycle-contract- Create/update contract
GET /api/drift-alerts- List drift alertsGET /api/drift-alerts/stats- Get drift statisticsPOST /api/drift-alerts/:id/ack- Acknowledge alertPOST /api/drift-alerts/:id/resolve- Resolve alertGET /api/remediation-jobs- List remediation jobsGET /api/remediation-jobs/stats- Get remediation statisticsPOST /api/remediation-jobs/:id/approve- Approve jobPOST /api/remediation-jobs/:id/reject- Reject job
- Google Cloud SDK installed and authenticated
- Docker Desktop installed and running
- Terraform >= 1.6 installed
- GCP project with billing enabled
gcloud services enable \
run.googleapis.com \
cloudtasks.googleapis.com \
cloudscheduler.googleapis.com \
sqladmin.googleapis.com \
secretmanager.googleapis.com \
artifactregistry.googleapis.com# Windows (PowerShell)
.\scripts\deploy.ps1 -ProjectId your-gcp-project-id
# Linux/Mac
chmod +x scripts/deploy.sh
./scripts/deploy.sh your-gcp-project-idThis script will:
- Create Artifact Registry repository
- Build and push Docker images
- Run Terraform to deploy Cloud Run, Cloud SQL, Cloud Tasks, etc.
If you prefer manual steps:
# 1. Configure variables
cd infra/gcp/terraform
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars with your values
# 2. Build and push images
REGION=us-central1
PROJECT_ID=your-project
docker build -t ${REGION}-docker.pkg.dev/${PROJECT_ID}/revops/api:latest -f apps/api/Dockerfile .
docker build -t ${REGION}-docker.pkg.dev/${PROJECT_ID}/revops/worker:latest -f apps/worker/Dockerfile .
docker build -t ${REGION}-docker.pkg.dev/${PROJECT_ID}/revops/web:latest -f apps/web/Dockerfile .
gcloud auth configure-docker ${REGION}-docker.pkg.dev
docker push ${REGION}-docker.pkg.dev/${PROJECT_ID}/revops/api:latest
docker push ${REGION}-docker.pkg.dev/${PROJECT_ID}/revops/worker:latest
docker push ${REGION}-docker.pkg.dev/${PROJECT_ID}/revops/web:latest
# 3. Deploy with Terraform
terraform init
terraform apply| Resource | Tier | Est. Monthly Cost |
|---|---|---|
| Cloud SQL | db-f1-micro | ~$9 |
| Cloud Run (API) | 0-10 instances | ~$0-5 |
| Cloud Run (Worker) | 0-5 instances | ~$0-3 |
| Cloud Run (Web) | 0-3 instances | ~$0-2 |
| Cloud Tasks | Free tier | $0 |
| Cloud Scheduler | 3 jobs | $0.10 |
| Total | ~$15-25/month |
Costs assume minimal traffic. Scale to zero when idle.
- Note the output URLs (api_url, web_url, webhook_url)
- Update your HubSpot app webhook URL to:
${api_url}/webhooks/hubspot - Update OAuth redirect URI to:
${api_url}/integrations/hubspot/callback - Visit the web dashboard to connect your HubSpot account
Create a HubSpot app at https://developers.hubspot.com with:
crm.objects.contacts.readcrm.objects.contacts.writecrm.objects.owners.readcrm.objects.tasks.writeoauth
contact.creationcontact.propertyChange(for lifecyclestage property)
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
TOKEN_ENC_KEY |
32+ char encryption key |
HUBSPOT_CLIENT_ID |
HubSpot OAuth app ID |
HUBSPOT_CLIENT_SECRET |
HubSpot OAuth secret |
HUBSPOT_REDIRECT_URI |
OAuth callback URL |
HUBSPOT_WEBHOOK_SECRET |
Webhook signature secret |
QUEUE_MODE |
local or gcp |
REDIS_URL |
Redis URL (for local mode) |
ADMIN_API_KEY |
Dashboard auth key (production) |
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
TOKEN_ENC_KEY |
Same as API |
HUBSPOT_CLIENT_ID |
HubSpot OAuth app ID |
HUBSPOT_CLIENT_SECRET |
HubSpot OAuth secret |
HUBSPOT_RPS_LIMIT |
API rate limit (default: 5) |
| Variable | Description |
|---|---|
API_BASE |
API service URL (server-side, for rewrites) |
- HubSpot Request Validation (X-HubSpot-Signature-V3)
- HubSpot Webhooks API (v3) Guide
- HubSpot API Usage Guidelines (5 req/sec, 200/page)
- HubSpot OAuth Token Refresh
- Cloud Scheduler to Cloud Run
MIT