Next.js
Env
NEXT_PUBLIC_KEVERD_PUBLIC_KEY=kv_pk_test_…
KEVERD_SECRET_KEY=kv_sk_test_…
npm install @keverdjs/react @keverd/node
Provider (App Router)
// app/components/KeverdWrapper.tsx
'use client';
import { KeverdProvider } from '@keverdjs/react';
export function KeverdWrapper({ children }: { children: React.ReactNode }) {
return (
<KeverdProvider apiKey={process.env.NEXT_PUBLIC_KEVERD_PUBLIC_KEY!}>
{children}
</KeverdProvider>
);
}
KeverdWrapper in app/layout.tsx.
Client collect
'use client';
import { useKeverdVisitorData } from '@keverdjs/react';
export default function LoginPage() {
const { getData, isLoading } = useKeverdVisitorData({ immediate: false });
async function login() {
const visitor = await getData();
await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ eventId: visitor.requestId }),
});
}
return (
<button disabled={isLoading} onClick={() => void login()}>
Continue
</button>
);
}
Server verify
// app/api/login/route.ts
import { Keverd } from '@keverd/node';
import { NextResponse } from 'next/server';
const keverd = new Keverd({ secretKey: process.env.KEVERD_SECRET_KEY! });
export async function POST(req: Request) {
const { eventId } = await req.json();
const decision = await keverd.verify(eventId);
if (decision.action === 'block') {
return NextResponse.json(
{ error: 'Blocked', reasons: decision.reasons },
{ status: 403 },
);
}
return NextResponse.json({ ok: true, visitorId: decision.visitor_id });
}
