> For an index of all Botscent documentation, see https://botscent.nibnalin.me/llms.txt.

# Next.js

Add both halves of Botscent to a Next.js app and check the install.

Add Botscent to a Next.js app. The page half runs in the browser from `instrumentation-client.ts`. The server half runs in `proxy.ts`.

## Before you start

You need:

* Next.js 15.3 or later. For Next.js 14 to 15.2, see [Older versions](#older-versions).
* Node.js 22.12 or later.

## 1. Install the package

Install `botscent` from npm.

```sh title="Terminal"
npm install botscent
```

With pnpm, yarn or bun, use their `add` command.

## 2. Add the page half

In `instrumentation-client.ts` in the project root, import `botscent/auto`. If the file exists, add the line to the existing file.

```ts title="instrumentation-client.ts"
import 'botscent/auto'
```

The page half now starts before hydration.

## 3. Add the server half

If the project has no proxy, create `proxy.ts` in the project root. Export the Botscent proxy from the file.

```ts title="proxy.ts"
export { proxy } from 'botscent/next'
```

On Vercel, the proxy now sends the request's own verdict to the page in a `Server-Timing` header.

If the project already has a proxy, wrap its function with `withBotscent` from `botscent/next`. Keep your own code as it is.

```ts title="proxy.ts"
import { NextResponse, type NextRequest } from 'next/server'
import { withBotscent } from 'botscent/next'

function existingProxy(request: NextRequest) {
  if (request.nextUrl.pathname === '/old') return NextResponse.redirect(new URL('/new', request.url))
  return NextResponse.next()
}

export const proxy = withBotscent(existingProxy)
```

The response of your proxy stays the same, except for `Server-Timing` and, for agents, `Cache-Control`.

> **Warning:** Do not replace an existing proxy with `export { proxy } from 'botscent/next'`. The replacement removes your own proxy code, such as redirects and access checks. Wrap the existing function with `withBotscent`.

## 4. Read the verdict

You can read the verdict in a client component and in a route handler.

In a client component, call `useBotscent` from `botscent/react`. The component renders again when the page verdict changes.

```tsx title="app/verdict.tsx"
'use client'
import { useBotscent } from 'botscent/react'

export function VerdictView() {
  const verdict = useBotscent()
  return <pre>{JSON.stringify(verdict)}</pre>
}
```

In a normal browser, the component shows `{"type":"human","reasons":[]}`.

In a route handler, call `inspect` from `botscent/server` with the request. `inspect` returns the request's own verdict.

```ts title="app/api/checkout/route.ts"
import { inspect } from 'botscent/server'

export async function POST(request: Request) {
  const verdict = await inspect(request)
  return Response.json(verdict)
}
```

The route handler now returns the request's own verdict as JSON.

> **Warning:** Do not use `agent_name` or the page verdict to allow access. Anyone can send the headers that produce a name, and the browser computes the page verdict. Use `isVerified` on the request's own verdict, as [The trust model](/docs/trust-model) describes.

## 5. Check the install

Start the app. Then run the check against its URL.

```sh title="Terminal"
npx botscent check http://localhost:3000/
```

The `page-script` check prints `pass`, and the command exits with code 0.

On your own server, the `server-half` check prints `unknown`, because the transport is off there. See [From the server to the page](/docs/server-to-page). On Vercel, the `server-half` check prints `pass`.

If a check fails, see [Verify your install](/docs/verify).

## Older versions

Before Next.js 15.3, Next.js has no `instrumentation-client.ts`. Render `<Botscent />` from `botscent/react` once in the root layout.

```tsx title="app/layout.tsx"
import { Botscent } from 'botscent/react'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Botscent />
        {children}
      </body>
    </html>
  )
}
```

Before Next.js 16, the proxy file is `middleware.ts`. Export the Botscent proxy under the name `middleware`.

```ts title="middleware.ts"
export { proxy as middleware } from 'botscent/next'
```

If the project already has a middleware, wrap its function with `withBotscent`.

```ts title="middleware.ts"
import { NextResponse, type NextRequest } from 'next/server'
import { withBotscent } from 'botscent/next'

function existingMiddleware(request: NextRequest) {
  if (request.nextUrl.pathname === '/old') return NextResponse.redirect(new URL('/new', request.url))
  return NextResponse.next()
}

export const middleware = withBotscent(existingMiddleware)
```

## Next steps

* [The verdict](/docs/verdict): Read what `type`, `agent_name` and `reasons` mean.
* [From the page to the server](/docs/page-to-server): Send the page verdict to a route handler with `reportHeaders`.
* [Server API (TypeScript)](/docs/server-api#inspect): Read every option of `inspect` and `withBotscent`.
* [examples/next](https://github.com/nalinbhardwaj/botscent/tree/main/examples/next): Run a Next.js app with both halves.
