Back to Integrations
Full-Stack Framework

Herald + Next.js

Use Next.js App Router to build a full-stack notification dashboard. Server-side API routes keep your Herald API key secure, while React client components provide an interactive UI for sending notifications, checking delivery status, and managing webhooks.

Ready to ship?

Start sending zero-PII notifications in minutes.

REGISTER YOUR WALLET
ZK-SECURE SOLANA NATIVE

Package: @herald-protocol/sdk

Install: npm install @herald-protocol/sdk

View full example on GitHub →

Initialize SDK

Create a server-side Herald client — never imported in client components.

Source →
Next.js / Initialize SDK
1
2
3
4
5
import { Herald } from '@herald-protocol/sdk';
export const herald = new Herald({
apiKey: process.env.HERALD_API_KEY!,
});

Send Notification (API Route)

POST /api/notify route handler for sending a single notification.

Source →
Next.js / Send Notification (API Route)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { NextRequest, NextResponse } from 'next/server';
import { herald } from '../../../lib/herald';
export async function POST(req: NextRequest) {
const body = await req.json();
const { wallet, subject, body: messageBody, category, idempotencyKey } = body;
if (!wallet || !subject) {
return NextResponse.json({ error: 'wallet and subject are required' }, { status: 400 });
}
const result = await herald.notify({
wallet,
subject,
body: messageBody,
category: category ?? 'defi',
receipt: true,
idempotencyKey,
});
return NextResponse.json(result, { status: 202 });
}

Webhook Handler

Verify HMAC-SHA256 signatures and handle delivery events.

Source →
Next.js / Webhook Handler
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { NextRequest, NextResponse } from 'next/server';
import { Herald } from '@herald-protocol/sdk';
const WEBHOOK_SECRET = process.env.HERALD_WEBHOOK_SECRET!;
export async function POST(req: NextRequest) {
const signature = req.headers.get('x-herald-signature');
const payload = await req.json();
const rawBody = JSON.stringify(payload);
if (!signature || !WEBHOOK_SECRET) {
return NextResponse.json({ error: 'Missing signature or secret' }, { status: 401 });
}
const isValid = await Herald.verifyWebhookSignature(rawBody, signature, WEBHOOK_SECRET);
if (!isValid) {
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
}
switch (payload.event) {
case 'delivery.confirmed':
console.log(`${payload.notificationId} delivered`);
break;
case 'delivery.failed':
console.error(`${payload.notificationId} failed: ${payload.error}`);
break;
}
return NextResponse.json({ received: true });
}

Send from Client Component

React client component calling the API route.

Next.js / Send from Client Component
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
'use client';
export function SendNotification() {
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const data = new FormData(e.currentTarget);
const res = await fetch('/api/notify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
wallet: data.get('wallet'),
subject: data.get('subject'),
body: data.get('body'),
}),
});
const result = await res.json();
console.log('Notification sent:', result.notificationId);
}
return (
<form onSubmit={handleSubmit}>
<input name="wallet" placeholder="Wallet address" required />
<input name="subject" placeholder="Subject" required />
<textarea name="body" placeholder="Message body" />
<button type="submit">Send Notification</button>
</form>
);
}

Common Patterns

Server-side API routes with route handlers
Client dashboard with React components
Webhook endpoint for delivery callbacks
Delivery status polling

Start building with Herald

Clone the examples repo, copy the code that fits your stack, and deploy.