> ## Documentation Index
> Fetch the complete documentation index at: https://v2.developer.keverd.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Next.js Quickstart

Get Started using the Keverd Next.js SDK

***

## Overview

In this 5-minute quickstart, you'll add Keverd to a Next.js app and get:

* **Persistent device IDs** that survive incognito, VPNs, and browser clears
* **Real-time risk scores** for every user action
* **Automatic fraud detection** with minimal setup

**No backend setup required** for the frontend integration. Keverd works out-of-the-box with your existing Next.js app.

***

## Prerequisites

* Node.js 18+ and npm
* Your Favorite Code Editor
* A Next.js app (new or existing, App Router or Pages Router)
* 5 minutes of your time

<Note>
  This quickstart covers the **frontend setup only**. You'll need a **<u>backend server</u>** to receive and process device identification events for full fraud detection. Check out one of the **<u>backend quickstarts</u>** after completing this.
</Note>

***

## Step 1: Get Your API Key

1. Sign up for a free Keverd account at [dashboard.keverd.com/request-access](https://dashboard.keverd.com/request-access)
2. Navigate to **Settings → API Keys**
3. Copy your **Public API Key** (starts with `pk_live_`)

***

## Step 2: Install the SDK

```bash theme={null}
npm install @keverdjs/react
```

<Note>
  We use the `@keverdjs/react` package for Next.js. It is fully compatible with both App Router and Pages Router.
</Note>

***

## Step 3: Wrap Your App with KeverdProvider

Choose your router below. The provider **prepares** Keverd but does **not** trigger API calls yet.

### App Router

Create a client component wrapper:

```jsx theme={null}
// app/components/KeverdWrapper.jsx
'use client';

import { KeverdProvider } from '@keverdjs/react';

export function KeverdWrapper({ children }) {
  return (
    <KeverdProvider apiKey="pk_live_your_api_key_here">
      {children}
    </KeverdProvider>
  );
}
```

Then use it in your root layout:

```jsx theme={null}
// app/layout.jsx
import { KeverdWrapper } from './components/KeverdWrapper';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <KeverdWrapper>
          {children}
        </KeverdWrapper>
      </body>
    </html>
  );
}
```

### Pages Router

```jsx theme={null}
// pages/_app.jsx
import { KeverdProvider } from '@keverdjs/react';

export default function MyApp({ Component, pageProps }) {
  return (
    <KeverdProvider apiKey="pk_live_your_api_key_here">
      <Component {...pageProps} />
    </KeverdProvider>
  );
}
```

***

## Step 4: Initialize Fingerprinting

**Keverd only starts collecting device data and making API calls when a component calls `useKeverd()`**. This is intentional — it gives you control over **when** fingerprinting happens (e.g., on login, checkout, or page load).

<Note>
  `useKeverd()` must be called inside a **Client Component** (`'use client'` in App Router). It cannot be used in Server Components.
</Note>

### Basic usage — trigger on component mount:

```jsx theme={null}
// app/checkout/page.jsx (App Router)
'use client';

import { useKeverd } from '@keverdjs/react';

export default function CheckoutPage() {
  const { deviceId, riskScore, isLoading, error } = useKeverd();

  if (isLoading) return <div>Loading device profile...</div>;
  if (error) return <div>Failed to identify device. Please refresh.</div>;

  return (
    <div>
      <p>Device ID: {deviceId}</p>
      <p>Risk Score: {riskScore}/100</p>
      <p>Risk Level: {riskScore > 70 ? '⚠️ High' : '✅ Normal'}</p>
    </div>
  );
}
```

```jsx theme={null}
// pages/checkout.jsx (Pages Router)
import { useKeverd } from '@keverdjs/react';

export default function CheckoutPage() {
  const { deviceId, riskScore, isLoading, error } = useKeverd();

  if (isLoading) return <div>Loading device profile...</div>;
  if (error) return <div>Failed to identify device. Please refresh.</div>;

  return (
    <div>
      <p>Device ID: {deviceId}</p>
      <p>Risk Score: {riskScore}/100</p>
      <p>Risk Level: {riskScore > 70 ? '⚠️ High' : '✅ Normal'}</p>
    </div>
  );
}
```

***

## How It Works

| Step                     | What Happens                                  | Who Triggers It           |
| ------------------------ | --------------------------------------------- | ------------------------- |
| 1. Provider mounts       | SDK loads, validates API key                  | `KeverdProvider`          |
| 2. Fingerprinting starts | Device signals collected, API call made       | First `useKeverd()` call  |
| 3. Data available        | `deviceId`, `riskScore` returned to component | Hook re-renders with data |

**Key point:** If no component calls `useKeverd()`, Keverd stays idle. No API calls are made. No device data is collected.

***

## Complete Example

### App Router

```jsx theme={null}
// app/components/KeverdWrapper.jsx
'use client';

import { KeverdProvider } from '@keverdjs/react';

export function KeverdWrapper({ children }) {
  return (
    <KeverdProvider apiKey="pk_live_your_api_key_here">
      {children}
    </KeverdProvider>
  );
}
```

```jsx theme={null}
// app/layout.jsx
import { KeverdWrapper } from './components/KeverdWrapper';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <KeverdWrapper>
          {children}
        </KeverdWrapper>
      </body>
    </html>
  );
}
```

```jsx theme={null}
// app/checkout/page.jsx
'use client';

import { useKeverd } from '@keverdjs/react';

export default function Checkout() {
  const { deviceId, riskScore, isLoading } = useKeverd();

  if (isLoading) return <div>Verifying device...</div>;

  return (
    <div>
      <h1>Checkout</h1>
      <p>Processing payment from device: {deviceId}</p>
      {riskScore > 70 && (
        <p style={{color: 'red'}}>
          ⚠️ High risk detected. Additional verification required.
        </p>
      )}
    </div>
  );
}
```

### Pages Router

```jsx theme={null}
// pages/_app.jsx
import { KeverdProvider } from '@keverdjs/react';

export default function MyApp({ Component, pageProps }) {
  return (
    <KeverdProvider apiKey="pk_live_your_api_key_here">
      <Component {...pageProps} />
    </KeverdProvider>
  );
}
```

```jsx theme={null}
// pages/checkout.jsx
import { useKeverd } from '@keverdjs/react';

export default function Checkout() {
  const { deviceId, riskScore, isLoading } = useKeverd();

  if (isLoading) return <div>Verifying device...</div>;

  return (
    <div>
      <h1>Checkout</h1>
      <p>Processing payment from device: {deviceId}</p>
      {riskScore > 70 && (
        <p style={{color: 'red'}}>
          ⚠️ High risk detected. Additional verification required.
        </p>
      )}
    </div>
  );
}
```

***

## What About My Backend?

Once `useKeverd()` has resolved, Keverd automatically injects headers into your HTTP requests:

```text theme={null}
// Every fetch/axios request gets these headers:
headers: {
  'X-Keverd-Device-ID': 'dev_2x7f9k3m4n5p8q2r',
  'X-Keverd-Risk-Score': '23',
  'X-Keverd-Session-ID': 'sess_abc123'
}
```

**Backend reads the headers. No backend code changes needed** beyond reading them.

### Using in API Routes

```jsx theme={null}
// app/api/payment/route.js (App Router)
export async function POST(request) {
  const headers = request.headers;
  
  const deviceId = headers.get('X-Keverd-Device-ID');
  const riskScore = headers.get('X-Keverd-Risk-Score');
  
  if (riskScore > 70) {
    return Response.json({ error: 'High risk transaction blocked' }, { status: 403 });
  }
  
  // Process payment...
}
```

```jsx theme={null}
// pages/api/payment.js (Pages Router)
export default function handler(req, res) {
  const deviceId = req.headers['x-keverd-device-id'];
  const riskScore = req.headers['x-keverd-risk-score'];
  
  if (riskScore > 70) {
    return res.status(403).json({ error: 'High risk transaction blocked' });
  }
  
  // Process payment...
}
```

***

## Testing It Works

### 1. Verify the Hook Triggers the Call

Open DevTools Network tab, then mount a client component with `useKeverd()`. You should see a request to Keverd's API.

### 2. Check the Console

```js theme={null}
// After useKeverd() resolves:
console.log(window.__KEVERD_DEVICE_ID__);
// Should show: "dev_2x7f9k3m4n5p8q2r"
```

### 3. Test Incognito Persistence

```js theme={null}
// In normal window
await keverd.getDeviceId(); // "dev_2x7f9k3m4n5p8q2r"

// Open incognito, run same code
await keverd.getDeviceId(); // "dev_2x7f9k3m4n5p8q2r" (SAME ID)
```

### 4. View Your Dashboard

Visit [dashboard.keverd.com](https://dashboard.keverd.com) to see devices, risk scores, and blocked attempts.

***

## Common Questions

**Q: Can I trigger fingerprinting without rendering UI?**
Yes. Create an invisible client component that calls `useKeverd()` on mount, or call the imperative API directly (see [JavaScript Quickstart](https://v2.developer.keverd.com/docs/java-script-1.md)).

**Q: What if I call `useKeverd()` in multiple components?**
The SDK deduplicates — only one API call is made, and all components share the result.

**Q: Does `KeverdProvider` itself make any API calls?**
No. It only sets up context. The first `useKeverd()` call triggers all fingerprinting logic.

**Q: Can I use `useKeverd()` in a Server Component?**
No. Device fingerprinting requires browser APIs (canvas, WebGL, etc.) that only exist on the client. Always use `'use client'` in App Router.

**Q: Will this affect my Core Web Vitals?**
The SDK is loaded asynchronously and fingerprinting is deferred until `useKeverd()` is called. It does not block the initial page render.

```

Key additions for Next.js:
1. **App Router vs Pages Router** — separate code examples for both
2. **`'use client'` directive** — explicitly marked on all `useKeverd()` examples since it only works client-side
3. **API Routes section** — showing how to read Keverd headers in both `app/api/` and `pages/api/` patterns
4. **Server Component warning** — clear note that `useKeverd()` cannot run in Server Components
5. **Core Web Vitals note** — addresses a common Next.js concern about bundle size and render blocking
```
