# Manual installation

Learn the steps to manually integrate Croct into your Next.js project.

The following guide gives you a step-by-step overview of how to install and initialize the SDK in your project.

> **Speed up your integration!**
>
> The CLI can fully automate the integration process for you. Check out the [integration guide](/reference/sdk/nextjs/integration) to get started faster.

## Install the SDK \[#install]

Run the following command to install the SDK:

**Command to install the SDK**

**npm**

```sh
npm install @croct/plug-next
```

**pnpm**

```sh
pnpm add @croct/plug-next
```

**Yarn**

```sh
yarn add @croct/plug-next
```

**Bun**

```sh
bun add @croct/plug-next
```

## Set up environment variables \[#environment-variables]

> **Required permissions**
>
> When generating the [API key](/explanation/application/api-keys), check the **Issue user tokens** permission to allow the SDK to generate [signed tokens](/explanation/application/signed-tokens).

Add the following environment variables to your project replacing the placeholders with your [Application ID](https://app.croct.com/redirect/organizations/-organization-/workspaces/-workspace-/applications/-application-/integration) and [API Key](https://app.croct.com/redirect/organizations/-organization-/workspaces/-workspace-/applications/-application-/keys):

**.env.local**

```bash
NEXT_PUBLIC_CROCT_APP_ID=<APPLICATION_ID>
CROCT_API_KEY=<API_KEY>
```

For a list of all available environment variables, see the [Environment variables](api/environment-variables) reference.

## Configure the middleware \[#middleware]

Choose a section below based on whether your project already uses middleware.

### New middleware

Create a new middleware file in the root of your project:

**Next ≤ 15 — JavaScript**

```js
export {middleware} from '@croct/plug-next/middleware';

export const config = {
  matcher: "/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"
};
```

**Next ≤ 15 — TypeScript**

```ts
export {middleware} from '@croct/plug-next/middleware';

export const config = {
  matcher: "/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"
};
```

**Next ≥ 16 — JavaScript**

```js
export {proxy} from '@croct/plug-next/proxy';

export const config = {
  matcher: "/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"
};
```

**Next ≥ 16 — TypeScript**

```ts
export {proxy} from '@croct/plug-next/proxy';

export const config = {
  matcher: "/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"
};
```

### Existing middleware

Use the [`withCroct`](api/functions/with-croct) function to wrap your existing middleware as shown in the example below:

**Next ≥ 16 — JavaScript**

```diff
import {NextResponse} from 'next/server';
import {withCroct} from '@croct/plug-next/proxy';

-export const config = {
+const config = {
  matcher: '/about/:path*',
}

-export function proxy(request) {
+function log(request) {
  // Your proxy logic here
  return NextResponse.next();
}

+export const proxy = withCroct(log, {matcher: config.matcher});
```

**Next ≥ 16 — TypeScript**

```diff
import {NextResponse, type NextRequest} from 'next/server';
import {withCroct} from '@croct/plug-next/proxy';

-export const config = {
+const config = {
    matcher: '/about/:path*',
}

-export function proxy(request: NextRequest): NextResponse {
+function log(request: NextRequest): NextResponse {
  // Your proxy logic here
  return NextResponse.next();
}

+export const proxy = withCroct(log, {matcher: config.matcher});
```

**Next ≤ 15 — JavaScript**

```diff
import {NextResponse} from 'next/server';
import {withCroct} from '@croct/plug-next/middleware';

-export const config = {
+const config = {
  matcher: '/about/:path*',
}

-export function middleware(request) {
+function log(request) {
  // Your middleware logic here
  return NextResponse.next();
}

+export const middleware = withCroct(log, {matcher: config.matcher});
```

**Next ≤ 15 — TypeScript**

```diff
import {NextResponse, type NextRequest} from 'next/server';
import {withCroct} from '@croct/plug-next/middleware';

-export const config = {
+const config = {
    matcher: '/about/:path*',
}

-export function middleware(request: NextRequest): NextResponse {
+function log(request: NextRequest): NextResponse {
  // Your middleware logic here
  return NextResponse.next();
}

+export const middleware = withCroct(log, {matcher: config.matcher});
```

## Initialize the provider \[#initialize]

Add the [`<CroctProvider>`](api/components/croct-provider) component to the root of your application:

**App router — JavaScript**

```diff
+import {CroctProvider} from '@croct/plug-next/CroctProvider';

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

**App router — TypeScript**

```diff
import type {ReactNode} from 'react';
+import {CroctProvider} from '@croct/plug-next/CroctProvider';

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

**Page router — JavaScript**

```diff
+import {CroctProvider} from '@croct/plug-next/CroctProvider';

export default function App({Component, pageProps}) {
  return (
+    <CroctProvider>
      <Component {...pageProps} />
+    </CroctProvider>
  );
}
```

**Page router — TypeScript**

```diff
import type {ReactElement} from 'react';
import type {AppProps} from 'next/app';
+import {CroctProvider} from '@croct/plug-next/CroctProvider';

export default function App({Component, pageProps}: AppProps): ReactElement {
  return (
+    <CroctProvider>
      <Component {...pageProps} />
+    </CroctProvider>
  );
}
```

## Check your integration \[#check]

If you open your application now, it should start sending events.

To check if your integration is working, go to the [Integration page](https://app.croct.com/redirect/organizations/-organization-/workspaces/-workspace-/applications/-application-/integration) of your application.

![Integration status](/assets/reference/sdk/integration-status.png)

When working correctly, you should see a green bullet next to the **Status** label saying **"Received traffic in the past 24 hours"**. If you still do not see this message after a few minutes, see the [Troubleshooting](troubleshooting) reference.

## Explore

- [CLI](integration): Learn how to use our CLI to get started faster.
- [Troubleshooting](troubleshooting): Identify and resolve issues with your integration.
