npm package: @deadendai/nextjs
Description: Official Next.js integration for deadend.ai - Revenue Recovery Platform
Author: deadend.ai
Latest version: 0.1.3

# @deadendai/nextjs

Official Next.js integration for [deadend.ai](https://deadend.ai) - the Revenue Recovery Platform.

This package provides server-side API proxy handlers for integrating deadend.ai with your Next.js application. It handles:

- **404 Event Tracking** - Track when users encounter page not found errors
- **Click Event Tracking** - Track when users click on search suggestions
- **Suggest API** - Get semantic search suggestions for 404 paths

## Installation

```bash
npm install @deadendai/nextjs
# or
yarn add @deadendai/nextjs
# or
pnpm add @deadendai/nextjs
```

## Environment Variables

Add your deadend.ai credentials to your environment:

```env
DEADEND_HOST=https://api.deadend.ai
DEADEND_API_KEY=your_api_key_here
```

> **Note:** Never expose your API key to the browser. This package is designed for server-side use only.

## Quick Start

### Option 1: Unified Handler (Recommended)

Create a single catch-all route that handles all deadend API requests:

```ts
// app/api/deadend/[[...path]]/route.ts
import { createDeadendHandlers, SearchThreshold } from '@deadendai/nextjs';

const handlers = createDeadendHandlers({
  limit: 5,
  searchThreshold: SearchThreshold.GOOD,
});

export const POST = handlers.POST;
```

The unified handler automatically detects the request type based on the payload:

- **Click Event**: Contains `clicked_url` and `search_id`
- **404 Event**: Contains `raw_path` only
- **Suggest**: Contains `path` field

### Option 2: Separate Handlers

Create individual routes for each endpoint:

```ts
// app/api/deadend/events/click/route.ts
import { createClickEventHandler } from '@deadendai/nextjs';

export const POST = createClickEventHandler();
```

```ts
// app/api/deadend/events/404/route.ts
import { createNotFoundEventHandler } from '@deadendai/nextjs';

export const POST = createNotFoundEventHandler();
```

```ts
// app/api/deadend/suggest/route.ts
import { createSuggestHandler, SearchThreshold } from '@deadendai/nextjs';

export const POST = createSuggestHandler({
  limit: 5,
  searchThreshold: SearchThreshold.VERY_GOOD,
});
```

## Configuration

All handlers accept a configuration object:

```ts
interface DeadendConfig {
  // Maximum number of results from suggest API (default: 3)
  limit?: number;

  // Minimum similarity threshold (default: SearchThreshold.GOOD / 0.7)
  searchThreshold?: SearchThreshold | number;

  // URLs to exclude from search results
  excludeUrls?: string[];

  // Custom API host (default: DEADEND_HOST env var or https://api.deadend.ai)
  host?: string;

  // Custom API key (default: DEADEND_API_KEY env var)
  apiKey?: string;
}
```

## Search Thresholds

The package exports a `SearchThreshold` enum with 5 preset levels:

```ts
import { SearchThreshold } from '@deadendai/nextjs';

// Available thresholds:
SearchThreshold.EXCELLENT  // 0.9 - Nearly exact matches only
SearchThreshold.VERY_GOOD  // 0.8 - Highly relevant results
SearchThreshold.GOOD       // 0.7 - Recommended default
SearchThreshold.MODERATE   // 0.6 - Broader coverage
SearchThreshold.LOW        // 0.5 - Maximum recall
```

| Threshold   | Value | Description                         |
| ----------- | ----- | ----------------------------------- |
| `EXCELLENT` | 0.9   | Nearly exact matches only           |
| `VERY_GOOD` | 0.8   | Highly relevant results             |
| `GOOD`      | 0.7   | Recommended default for most cases  |
| `MODERATE`  | 0.6   | Broader coverage, some noise        |
| `LOW`       | 0.5   | Maximum recall, may include noise   |

## Client-Side Usage

After setting up the server-side handlers, you can call them from your client:

### Track 404 Events

```ts
// Call this when a 404 page is rendered
async function track404(path: string) {
  await fetch('/api/deadend', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      raw_path: path,
      origin: window.location.origin,
      referrer: document.referrer,
    }),
  });
}
```

### Get Suggestions

```ts
// Get suggestions for a 404 path
async function getSuggestions(path: string) {
  const response = await fetch('/api/deadend', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ path }),
  });

  const data = await response.json();
  return data; // { search_id, suggestions: [...] }
}
```

### Track Click Events

```ts
// Track when a user clicks a suggestion
async function trackClick(
  clickedUrl: string,
  clickedRank: number,
  rawPath: string,
  searchId: string
) {
  await fetch('/api/deadend', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      clicked_url: clickedUrl,
      clicked_rank: clickedRank,
      raw_path: rawPath,
      search_id: searchId,
      origin: window.location.origin,
    }),
  });
}
```

## API Reference

### Handlers

| Handler                      | Description                              |
| ---------------------------- | ---------------------------------------- |
| `createDeadendHandlers()`    | Unified handler for all endpoints        |
| `createClickEventHandler()`  | Handler for click events only            |
| `createNotFoundEventHandler()` | Handler for 404 events only            |
| `createSuggestHandler()`     | Handler for suggest requests only        |

### Types

```ts
// Event payloads
type ClickEventPayload = {
  clicked_url: string;
  clicked_rank: number;
  raw_path: string;
  search_id: string;
  origin?: string;
  timestamp?: string;
};

type NotFoundEventPayload = {
  raw_path: string;
  origin?: string;
  referrer?: string;
  user_agent?: string;
  user_ip?: string;
};

// Suggest types
type SuggestRequest = {
  path: string;
  limit?: number;
  options?: {
    excludeUrls?: string[];
    searchThreshold?: number;
  };
};

type SuggestResponse = {
  search_id: string;
  suggestions: Suggestion[];
  processed_path?: string;
};

type Suggestion = {
  url: string;
  title: string;
  description?: string;
  score: number;
};
```

### Type Guards

```ts
import { isClickEvent, isNotFoundEvent } from '@deadendai/nextjs';

// Check event type
if (isClickEvent(event)) {
  // Handle click event
}

if (isNotFoundEvent(event)) {
  // Handle 404 event
}
```

## Error Handling

The handlers return appropriate HTTP status codes:

| Status | Description                                    |
| ------ | ---------------------------------------------- |
| 204    | Success (events)                               |
| 200    | Success (suggest)                              |
| 400    | Bad request - missing or invalid parameters   |
| 401    | Unauthorized - invalid API key                |
| 403    | Forbidden - rate limit exceeded               |
| 405    | Method not allowed - only POST is supported   |
| 500    | Server error - configuration or network error |

## Architecture

```
Browser → Your Next.js API Route → deadend.ai API
```

This architecture ensures your API key is never exposed to the browser.

## Links

- [Documentation](https://docs.deadend.ai)
- [Events API Reference](https://docs.deadend.ai/api-reference/events)
- [Search API Reference](https://docs.deadend.ai/api-reference/search)
- [Dashboard](https://deadend.ai/dashboard)

## License

MIT © [deadend.ai](https://deadend.ai)