# NextJS

## Hosted on Vercel and other serverless platforms

When Next.js is hosted on Vercel and other serverless platforms, it has a suboptimal way to instrument API routes, which prevents us to properly detect traffic. Even the [instrumentation.ts](https://nextjs.org/docs/app/api-reference/file-conventions/instrumentation) doesn't fully work with OpenTelemetry as expected.

In these scenarios please follow [Custom Integration](/installation/sdk-installations/custom-integrations.md) guide to create a wrapper around API route handlers.

***

## Self-hosted as service&#x20;

If you're self-hosting NextJS you can use `next start` to get going.

### Installation guide

{% stepper %}
{% step %}

### Install using your favourite package manager

```
npm i @appear.sh/introspector // or
yarn add @appear.sh/introspector // or
pnpm add @appear.sh/introspector
```

{% endstep %}

{% step %}

### Initialise Appear in your app startup

Create the`instrumentation.ts` file with the following code:

{% code title="instrumentation.ts" overflow="wrap" %}

```typescript
export const register = async () => {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    // notice import from /nextjs entrypoint which comes with extra defaults
    const { registerAppear } = await import("@appear.sh/introspector/nextjs")
    registerAppear({
      apiKey: process.env.APPEAR_REPORTING_KEY,
      environment: process.env.NODE_ENV,
      serviceName: "User Service",
    })
  }
}
```

{% endcode %}

{% hint style="success" %}
Appear's NextJS SDK has a preconfigured filter to avoid NextJS noise - see blow.
{% endhint %}

The **Next.js preset** (`/nextjs` entrypoint) includes a built-in `defaultInterceptFilter`.\
By default, it ignores all `/_next/` routes and any non-JSON responses.

If you need to extend or customise this filter, you can import and build on it:

```typescript
import { defaultInterceptFilter } from "@appear.sh/introspector/nextjs"
```

{% endstep %}

{% step %}

### Update your start script

Update your start script and pass `NODE_OPTIONS` variable to register appear hook.&#x20;

{% hint style="success" %}
This ensures the Appear agent is loaded first, which is best practice for instrumentation agents.
{% endhint %}

```json
"scripts": {
  "start": "NODE_OPTIONS='--import ./appear.js' next start"
}
```

{% endstep %}

{% step %}

### Log into Appear to view entries

The introspector will begin reporting the structure of your API services when they're interacted with. Log into [Appear](broken://spaces/k1FE7BkpojojQWs9RfaQ/pages/fgXrRYhHPH6UqaisimYD) with your credentials to view the services that appear. You may need to refresh the page periodically.
{% endstep %}
{% endstepper %}

***

## Configuration

To configure how the introspector reports your schemas to Appear, you can adjust in the file below.

{% code title="config.ts" overflow="wrap" fullWidth="false" %}

```javascript
export interface AppearConfig {
  /**
   * API key used for reporting
   * you can obtain your reporting key in keys section in Appear settings
   * reporting keys have only the permission to report schema and can't read any data
   * you can use any method to inject the key, in examples we used env variable
   */
  apiKey: string
  /**
   * Environment where the report is sent from
   * it can be any string that identifies environment data are reported from.
   * Often used as "production" or "staging", however if you're using some form of ephemeral environment feel free to use its identifier
   */
  environment: string

  /**
   * Name of current service
   * used to improve accuracy of matching, useful when you're not using descriptive host names in incoming requests
   * for example if you're using directly IP addresses
   *
   * @optional
   * @default hostname if not provided the service name will be detected from hostname
   */
  serviceName?: string

  /**
   * A flag you can use to disable introspector completely
   * useful if you don't want to report in certain environments
   *
   * @default true
   */
  enabled?: boolean

  /**
   * Enable debug mode which will output detailed debug information to the console,
   * including all reported traffic, validation errors, and other diagnostic data.
   * Useful for troubleshooting and understanding what data is being sent to Appear.
   *
   * @default false
   */
  debug?: boolean

  /** configuration of how often and where data are reported */
  reporting?: {
    /**
     * endpoint reports are sent to, useful if you want to audit what data are reported
     * simple audit can be done by navigating to https://public.requestbin.com/r which will give you endpoint url you can paste here and see in the debugger all traffic
     *
     * @default https://api.appear.sh/v1/reports
     */
    endpoint?: string
  }

  interception?: {
    /**
     * Optional function that allows to filter what request/response pair is getting analyzed and reported.
     * You can reuse default filter by importing it from `import { defaultInterceptFilter } from "@appear.sh/introspector" and using it inside the function`
     *
     * @default (req, req, config) => req.destination === "" && !request.url.includes(config.reporting.endpoint)
     */
    filter?: (
      request: Request,
      response: Response,
      config: ResolvedAppearConfig,
    ) => boolean
  }
}
```

{% endcode %}

## Example of custom interception filter

In some situations it's desirable to filter out certain traffic from being reported to Appear. For example the service is redirecting unauthorized requests using 3XX status code which is normally considered as successful and it's creating noise.

```typescript
import {
  registerAppear,
  defaultInterceptFilter,
} from "@appear.sh/introspector/nextjs"

registerAppear({
  apiKey: process.env.APPEAR_REPORTING_KEY,
  environment: process.env.NODE_ENV,
  serviceName: "User Service",
  interception: {
    filter: (request, response, config) => {
      return (
        defaultInterceptFilter(request, response, config) &&
        !(response.status >= 300 && response.status < 400) // ignore redirects
      )
    },
  },
})
```

***

We're actively working on improving how Appear works with NextJS. If you have any queries or require support with the above instructions, please [contact us](/getting-started/get-in-touch.md).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.appear.sh/installation/sdk-installations/nextjs.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
