← GitHub integrations
TypeScript
GitHub webhook with Next.js App Router
Read request.text once, verify the signature, and only then parse JSON.
Code sample
Webhook endpoint
Code samples, header names, event names, and signatures remain verbatim across locales.
import crypto from 'node:crypto';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const body = await request.text();
const sent = request.headers.get('x-hub-signature-256') ?? '';
const expected = `sha256=${crypto.createHmac('sha256', process.env.GITHUB_WEBHOOK_SECRET!)
.update(body).digest('hex')}`;
const valid = sent.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sent), Buffer.from(expected));
if (!valid) return new NextResponse(null, { status: 401 });
await enqueue({ deliveryId: request.headers.get('x-github-delivery'),
event: request.headers.get('x-github-event'), payload: JSON.parse(body) });
return new NextResponse(null, { status: 202 });
}
Setup steps
Verify the first delivery
Setup steps 1
Create a workspace in DevLog and copy the endpoint and Secret.
Setup steps 2
Configure the same Secret in GitHub and in your application’s secure environment variable.
Setup steps 3
Send a ping and confirm the signature, Delivery ID, and payload in the inbox.