Implement Juicebox webhook handling. Use when setting up event notifications, processing webhooks, or integrating real-time updates from Juicebox. Trigger with phrases like "juicebox webhooks", "juicebox events", "juicebox notifications", "juicebox real-time".
/plugin marketplace add jeremylongshore/claude-code-plugins-plus-skills/plugin install juicebox-pack@claude-code-plugins-plusThis skill is limited to using the following tools:
Implement webhook handlers for real-time Juicebox events and notifications.
// First, configure in Juicebox dashboard or via API
import { JuiceboxClient } from '@juicebox/sdk';
const client = new JuiceboxClient({
apiKey: process.env.JUICEBOX_API_KEY!
});
await client.webhooks.create({
url: 'https://your-app.com/webhooks/juicebox',
events: [
'search.completed',
'profile.enriched',
'export.ready',
'quota.warning'
],
secret: process.env.JUICEBOX_WEBHOOK_SECRET
});
// routes/webhooks.ts
import { Router } from 'express';
import crypto from 'crypto';
const router = Router();
// Verify webhook signature
function verifySignature(payload: string, signature: string, secret: string): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(`sha256=${expected}`)
);
}
router.post('/webhooks/juicebox', express.raw({ type: 'application/json' }), async (req, res) => {
const signature = req.headers['x-juicebox-signature'] as string;
const payload = req.body.toString();
// Verify signature
if (!verifySignature(payload, signature, process.env.JUICEBOX_WEBHOOK_SECRET!)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(payload);
// Acknowledge receipt immediately
res.status(200).json({ received: true });
// Process event asynchronously
await processWebhookEvent(event);
});
export default router;
// services/webhook-processor.ts
interface WebhookEvent {
id: string;
type: string;
timestamp: string;
data: any;
}
export async function processWebhookEvent(event: WebhookEvent): Promise<void> {
console.log(`Processing event: ${event.type} (${event.id})`);
switch (event.type) {
case 'search.completed':
await handleSearchCompleted(event.data);
break;
case 'profile.enriched':
await handleProfileEnriched(event.data);
break;
case 'export.ready':
await handleExportReady(event.data);
break;
case 'quota.warning':
await handleQuotaWarning(event.data);
break;
default:
console.warn(`Unknown event type: ${event.type}`);
}
}
async function handleSearchCompleted(data: { searchId: string; resultCount: number }) {
// Notify user that search is complete
await notificationService.send({
type: 'search_complete',
searchId: data.searchId,
message: `Search completed with ${data.resultCount} results`
});
}
async function handleProfileEnriched(data: { profileId: string; fields: string[] }) {
// Update local cache with enriched data
await cacheService.invalidate(`profile:${data.profileId}`);
await db.profiles.update({
where: { id: data.profileId },
data: { enrichedAt: new Date() }
});
}
async function handleExportReady(data: { exportId: string; downloadUrl: string }) {
// Notify user and store download URL
await notificationService.send({
type: 'export_ready',
exportId: data.exportId,
downloadUrl: data.downloadUrl
});
}
async function handleQuotaWarning(data: { usage: number; limit: number }) {
// Alert team about quota usage
const percentage = (data.usage / data.limit) * 100;
if (percentage > 80) {
await alertService.send({
severity: 'warning',
message: `Juicebox quota at ${percentage.toFixed(1)}%`
});
}
}
// lib/webhook-queue.ts
import { Queue } from 'bullmq';
const webhookQueue = new Queue('juicebox-webhooks', {
connection: { host: 'localhost', port: 6379 }
});
export async function queueWebhookProcessing(event: WebhookEvent): Promise<void> {
await webhookQueue.add('process', event, {
attempts: 3,
backoff: {
type: 'exponential',
delay: 1000
}
});
}
// Worker
import { Worker } from 'bullmq';
new Worker('juicebox-webhooks', async (job) => {
await processWebhookEvent(job.data);
}, {
connection: { host: 'localhost', port: 6379 }
});
| Event | Description | Payload |
|---|---|---|
search.completed | Async search finished | searchId, resultCount |
profile.enriched | Profile data enriched | profileId, fields |
export.ready | Bulk export ready | exportId, downloadUrl |
quota.warning | Approaching quota limit | usage, limit |
key.rotated | API key rotated | newKeyPrefix |
| Issue | Cause | Solution |
|---|---|---|
| Invalid signature | Wrong secret | Verify webhook secret |
| Duplicate events | Network retry | Implement idempotency |
| Processing timeout | Slow handler | Use async queue |
After webhooks, see juicebox-performance-tuning for optimization.
This skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.