DEV Community

James
James

Posted on

I Built a Webhook Debugger in a Weekend — Here's What I Learned

I Built a Webhook Debugger in a Weekend — Here's What I Learned

Hooklog lets you capture, inspect, and replay any webhook with a single URL. No more blind integrations.


The Problem

You're integrating Stripe webhooks into your Node.js app. You've read the docs, you think you've got it right — but nothing fires in production. Your local environment can't receive webhooks. You have no idea what's being sent, what's failing, or why.

You add console.log(). You deploy. You wait for Stripe to fire again (up to 78 hours, according to their retry schedule). Still nothing.

This isn't a niche problem. It's every developer integrating Stripe, GitHub, Slack, Twilio, or any service that uses webhooks.

The Old Solution

Most developers solve this one of two ways:

  1. Ngrok + local server — great until you hit rate limits, need to share with a teammate, or forget to restart ngrok after a laptop sleep
  2. Write temporary logging middleware — works once, then you delete it and lose the code

What nobody has is a Postman for webhooks: one URL that captures everything, shows you what's broken, and lets you replay it.

Building Hooklog

I built Hooklog in a weekend. Here's the architecture:

The Core Idea

Give every developer a unique webhook URL on sign-up (no sign-up required for the free tier):

https://hooklog.c0c58bd.p.egbe.app/webhook/sec_your_endpoint_id
Enter fullscreen mode Exit fullscreen mode

Point any webhook at it. Hooklog captures:

  • Request headers
  • Request body (raw + parsed)
  • Response from your endpoint
  • Timing (time to first byte, total duration)
  • HTTP status code

Then you inspect it all in a dashboard.

The Stack

  • Frontend: Next.js 14 (App Router) + Tailwind CSS
  • Backend: Node.js + Express
  • Storage: JSONL files (MVP) — Postgres upgrade planned
  • Hosting: Docker on internal PaaS gateway
  • Payments: Stripe hosted checkout

The Tricky Parts

1. Next.js 14 Dynamic Routes

Next.js 14 changed how dynamic route params work — they're now Promises that must be awaited:

// Next.js 13
export async function GET(request: Request, { params }: { params: { id: string } }) {
  const { id } = params
}

// Next.js 14 — params is a Promise
export async function GET(request: Request, { params }: { params: Promise<{ id: string }> }) {
  const { id } = await params
}
Enter fullscreen mode Exit fullscreen mode

2. File Storage + Directory Creation

import { promises as fs } from 'fs';
import path from 'path';

async function saveEvent(endpointId: string, event: WebhookEvent) {
  const dir = path.join(process.cwd(), 'data', 'events', endpointId);
  await fs.mkdir(dir, { recursive: true }); // Don't forget recursive!
  const file = path.join(dir, `${Date.now()}.jsonl`);
  await fs.writeFile(file, JSON.stringify(event));
}
Enter fullscreen mode Exit fullscreen mode

3. Docker Multi-Stage Build

FROM node:20-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install && npm run build

FROM node:20-slim AS runner
WORKDIR /app
COPY --from=builder /app/.next/ ./.next/
COPY --from=builder /app/public/ ./public/
COPY --from=builder /app/node_modules/ ./node_modules/
EXPOSE 3000
CMD ["npm", "start"]
Enter fullscreen mode Exit fullscreen mode

What Hooklog Does

1. Capture Every Webhook — point any webhook at your Hooklog URL and it captures everything.

2. Inspect in Real-Time — headers, body, response status, timing, timestamp.

3. Replay Without Waiting — click Replay and fire immediately instead of waiting for Stripe's retry schedule (1h, 12h, 72h).

4. Failure Alerts — email immediately when your endpoint returns 4xx/5xx.

The Numbers

Launched 2026-03-27. After 4 hours: 0 paying customers, 0 signups. Real Stripe test-mode webhooks are hitting it though.

What's Next

  1. Adding analytics to understand where users drop off
  2. Setting up proper authentication
  3. Migrating from JSONL to Postgres
  4. Google Ads to drive targeted traffic

Try it: https://hooklog.c0c58bd.p.egbe.app/

Free tier: 10,000 events/month, 3-day retention, 3 endpoints.


Have a webhook debugging horror story? Drop it in the comments.

Top comments (0)