Centinel AnalyticaCentinel Analytica
PlatformsApplication

Next.js

Add Centinel Analytica to your Next.js application.

Overview

Centinel validates each request before it reaches your application. Suspicious requests are blocked or redirected to a verification page. The client script helps distinguish legitimate users from bots.

Blocked requests are redirected to /block by default. Create this page in your app or customize the redirect URL in your middleware configuration.

Prerequisites

  • Site key (public, used by the browser script)
  • Secret key (server-only, used for validation)

Install

In your Next.js project:

npm install @centinel/nextjs

Configure

Environment variables

Add your Centinel keys to .env:

CENTINEL_SITE_KEY=YOUR_SITE_KEY
CENTINEL_SECRET_KEY=YOUR_SECRET_KEY
NEXT_PUBLIC_CENTINEL_SITE_KEY=YOUR_SITE_KEY

Key safety

Use CENTINEL_SECRET_KEY server-side only. Don't expose it to the browser.

Which site key to use

Use CENTINEL_SITE_KEY for server-side code (layouts, middleware). Use NEXT_PUBLIC_CENTINEL_SITE_KEY if using CentinelLayout in client-side pages.

Client script

Add CentinelLayout to your root layout:

// app/layout.tsx (server-side)
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>
  );
}

Or if using in a client-side page:

// app/page.tsx (client-side)
'use client';
import { CentinelLayout } from '@centinel/nextjs';

export default function HomePage(): JSX.Element {
  return (
    <CentinelLayout siteKey={process.env.NEXT_PUBLIC_CENTINEL_SITE_KEY!}>
      {/* Your page content */}
    </CentinelLayout>
  );
}
Protection

Choose between automatic middleware or manual validation:

Create middleware.ts in your project root:

import { createCentinelMiddlewareFromEnv } from '@centinel/nextjs';

export default createCentinelMiddlewareFromEnv();

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

Use in specific API routes when middleware doesn't fit:

// 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);
}

Or with custom configuration:

// app/api/protected/route.ts
import { createRequestValidator } from '@centinel/nextjs';
import { NextRequest, NextResponse } from 'next/server';

const { isBot } = createRequestValidator({
  siteKey: 'YOUR_SITE_KEY',
  secretKey: 'YOUR_SECRET_KEY'
});

export async function POST(request: NextRequest) {
  if (await isBot(request)) {
    return NextResponse.json({ error: 'Access denied' }, { status: 403 });
  }
  
  // Your protected logic
}

Custom configuration

Pass config directly instead of using environment variables:

import { createCentinelMiddleware } from '@centinel/nextjs';

export default createCentinelMiddleware({
  siteKey: 'YOUR_SITE_KEY',
  secretKey: 'YOUR_SECRET_KEY'
});

Route matching

Specify which routes to protect:

export const config = {
  matcher: [
    '/api/:path*',        // All API routes
    '/dashboard/:path*',  // Dashboard pages
    '/admin/:path*'       // Admin area
  ]
};

Changelog

  • v1.2.2 — Response header passthrough

On this page