mcpField
V
vercel-webhooks

vercel-webhooks

github.com/hookdeckDevelopment95204 installsUpdated today
Repository

About vercel-webhooks

vercel-webhooks is a skill for developers handling Vercel webhooks. It covers deployment, project, domain, and integration events, with signature verification and handler examples for several frameworks.

Key features

  1. 01Webhook signature verification examples
  2. 02Deployment, project, and domain event reference
  3. 03Express, Next.js, and FastAPI examples
  4. 04Hookdeck CLI local tunnel instructions

Use cases

  1. 01Monitor deployment status and start follow-up tasks
  2. 02Notify a team when deployment fails
  3. 03Clean up external resources after project removal
  4. 04Inspect webhook requests locally

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/hookdeck/webhook-skills --skill vercel-webhooks

After installing, type/vercel-webhooksin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

TODO.md
examples/express/
.env.example
package.json
README.md
examples/express/src/
index.js
examples/express/test/
webhook.test.js
examples/fastapi/
.env.example
main.py
README.md
requirements.txt
test_webhook.py
examples/nextjs/
.env.example
package.json
README.md
vitest.config.ts
examples/nextjs/app/webhooks/vercel/
route.ts
examples/nextjs/test/
webhook.test.ts
references/
overview.md
setup.md
verification.md

Details

From the project README

Vercel Webhooks

When to Use This Skill

  • Setting up Vercel webhook handlers
  • Debugging signature verification failures
  • Understanding Vercel event types and payloads
  • Handling deployment, project, domain, or integration events
  • Monitoring deployment status changes

Essential Code (USE THIS)

Express Webhook Handler with Manual Verification
const express = require('express');
const crypto = require('crypto');

const app = express();

// CRITICAL: Use express.raw() for webhook endpoint - Vercel needs raw body
app.post('/webhooks/vercel',
  express.raw({ type: 'application/json' }),
  async (req, res) => {
    const signature = req.headers['x-vercel-signature'];

    if (!signature) {
      return res.status(400).send('Missing x-vercel-signature header');
    }

    // Verify signature using SHA1 HMAC
    const expectedSignature = crypto
      .createHmac('sha1', process.env.VERCEL_WEBHOOK_SECRET)
      .update(req.body)
      .digest('hex');

    // Use timing-safe comparison
    let signaturesMatch;
    try {
      signaturesMatch = crypto.timingSafeEqual(
        Buffer.from(signature),
        Buffer.from(expectedSignature)
      );
    } catch (err) {
      // Buffer length mismatch = invalid signature
      signaturesMatch = false;
    }

    if (!signaturesMatch) {
      console.error('Invalid Vercel webhook signature');
      return res.status(400).send('Invalid signature');
    }

    // Parse the verified payload
    const event = JSON.parse(req.body.toString());

    // Handle the event
    switch (event.type) {
      case 'deployment.created':
        console.log('Deployment created:', event.payload.deployment.id);
        break;
      case 'deployment.succeeded':
        console.log('Deployment succeeded:', event.payload.deployment.id);
        break;
      case 'deployment.error':
        console.log('Deployment failed:', event.payload.deployment.id);
        break;
      case 'project.created':
        console.log('Project created:', event.payload.project.name);
        break;
      default:
        console.log('Unhandled event:', event.type);
    }

    res.json({ received: true });
  }
);
Python (FastAPI) Webhook Handler
import os
import hmac
import hashlib
from fastapi import FastAPI, Request, HTTPException, Header

app = FastAPI()
webhook_secret = os.environ.get("VERCEL_WEBHOOK_SECRET")

@app.post("/webhooks/vercel")
async def vercel_webhook(
    request: Request,
    x_vercel_signature: str = Header(None)
):
    if not x_vercel_signature:
        raise HTTPException(status_code=400, detail="Missing x-vercel-signature header")

    # Get raw body
    body = await request.body()

    # Compute expected signature
    expected_signature = hmac.new(
        webhook_secret.encode(),
        body,
        hashlib.sha1
    ).hexdigest()

    # Timing-safe comparison
    if not hmac.compare_digest(x_vercel_signature, expected_signature):
        raise HTTPException(status_code=400, detail="Invalid signature")

    # Parse verified payload
    event = await request.json()

    # Handle event
    if event["type"] == "deployment.created":
        print(f"Deployment created: {event['payload']['deployment']['id']}")
    elif event["type"] == "deployment.succeeded":
        print(f"Deployment succeeded: {event['payload']['deployment']['id']}")
    # ... handle other events

    return {"received": True}

For complete working examples with tests, see:

Common Event Types

EventTriggered WhenCommon Use Cases
deployment.createdA new deployment startsStart deployment monitoring, notify team
deployment.succeededDeployment completes successfullyUpdate status, trigger post-deploy tasks
deployment.errorDeployment failsAlert team, rollback actions
deployment.canceledDeployment is canceledClean up resources
project.createdNew project is createdSet up monitoring, configure resources
project.removedProject is deletedClean up external resources
domain.createdDomain is addedUpdate DNS, SSL configuration

See references/overview.md for the complete event list.

Environment Variables

# Required
VERCEL_WEBHOOK_SECRET=your_webhook_secret_from_dashboard

# Optional (for API calls)
VERCEL_TOKEN=your_vercel_api_token

Local Development

For local webhook testing, install Hookdeck CLI:

Then start the tunnel:

npx hookdeck-cli listen 3000 vercel --path /webhooks/vercel

No account required. Provides local tunnel + web UI for inspecting requests.

Reference Materials

Recommended: webhook-handler-patterns

For production-ready webhook handling, also install the webhook-handler-patterns skill to learn:

Related Skills

Comments

Markdown supported