# Centinel Analytica Next.js Integration

Bot protection middleware for Next.js applications.

## Installation

```bash
npm install @centinel/nextjs
```

## Setup

### 1. Environment Variables

```env
CENTINEL_SITE_KEY=your_site_key_here
CENTINEL_SECRET_KEY=your_secret_key_here
NEXT_PUBLIC_CENTINEL_SITE_KEY=your_site_key_here
```

### 2. Client Script

```typescript
// app/layout.tsx
import { CentinelLayout } from '@centinel/nextjs';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <CentinelLayout siteKey={process.env.CENTINEL_SITE_KEY!}>
          {children}
        </CentinelLayout>
      </body>
    </html>
  );
}
```

### 3. Middleware

#### Simple Middleware

```typescript
import { createCentinelMiddlewareFromEnv } from '@centinel/nextjs';
import { NextRequest } from 'next/server';

const centinelMiddleware = createCentinelMiddlewareFromEnv();

export default async function middleware(request: NextRequest) {
  const result = await centinelMiddleware(request);
  return result.response;
}

export const config = {
  matcher: ['/api/:path*', '/dashboard/:path*']
};
```

#### With Multiple Middlewares

```typescript
import { createCentinelMiddleware } from '@centinel/nextjs';
import { NextRequest, NextResponse } from 'next/server';

const centinelMiddleware = createCentinelMiddleware({
  siteKey: process.env.CENTINEL_SITE_KEY!,
  secretKey: process.env.CENTINEL_SECRET_KEY!
});

export default async function middleware(request: NextRequest) {
  const result = await centinelMiddleware(request);

  if (result.should_intercept) {
    return result.response;
  }

  // Your other middleware logic
  return NextResponse.next();
}

export const config = {
  matcher: ['/api/:path*', '/dashboard/:path*']
};
```

#### Manual Validation (API Routes)

```typescript
// app/api/login/route.ts
import { createRequestValidatorFromEnv } from '@centinel/nextjs';
import { NextRequest, NextResponse } from 'next/server';

const { isBot } = createRequestValidatorFromEnv();

export async function POST(request: NextRequest) {
  if (await isBot(request)) {
    return NextResponse.json({ error: 'Blocked' }, { status: 403 });
  }
  return handleLogin(request);
}
```

## Advanced

### CentinelResult

```typescript
interface CentinelResult {
  response: NextResponse;
  decision: 'allow' | 'block' | 'redirect' | 'not_matched';
  should_intercept: boolean;
}
```

- `should_intercept: true` → `block` or `redirect` (return immediately)
- `should_intercept: false` → `allow` or `not_matched` (continue)

### CentinelMiddleware Class

```typescript
import { CentinelMiddleware } from '@centinel/nextjs';

const centinel = new CentinelMiddleware({
  siteKey: process.env.CENTINEL_SITE_KEY!,
  secretKey: process.env.CENTINEL_SECRET_KEY!,
  timeout: 1000,  // ms (default: 500)
  debugMode: true
});

const result = await centinel.validate({ request });
```

### Check Cookie in API Routes

```typescript
export async function POST(request: NextRequest) {
  if (!request.cookies.get('_centinel')) {
    return NextResponse.json({ error: 'Blocked' }, { status: 403 });
  }
  // ...
}
```
