npm package: @definitely-fine/nextjs
Description: Next.js request and server action helpers for definitely-fine scenarios.
Latest version: 0.1.1

# @definitely-fine/nextjs

`@definitely-fine/nextjs` connects `definitely-fine` scenario context to Next.js route handlers and server actions.

It reads a scenario id from a request header and runs server-side Next.js code inside the matching active scenario context.

## Installation

```bash
pnpm add definitely-fine @definitely-fine/nextjs
```

## Important

> [!IMPORTANT]
> Do not leave scenario activation enabled in production by accident.
>
> `@definitely-fine/nextjs` will activate scenario context whenever the request header is present.
> In production, pair this package with `createRuntime({ enabled: false })` in your core runtime, or avoid wrapping handlers and server actions there entirely.

Core runtime protection:

```ts
import { createRuntime } from "definitely-fine";

const runtime = createRuntime<DemoContract>({
  enabled: process.env.NODE_ENV !== "production",
});
```

Optional route-level guard:

```ts
import { withDefinitelyFineScenario } from "@definitely-fine/nextjs";

const postCounterResponse = async (_request: Request): Promise<Response> => {
  return Response.json({ ok: true });
};

export const POST =
  process.env.NODE_ENV === "production"
    ? postCounterResponse
    : withDefinitelyFineScenario(postCounterResponse);
```

## What This Package Does

This package does not replace the core runtime. You still create your scenarios and wrapped runtime with `definitely-fine`.

Its job is narrower:

- define the scenario header name constant
- read that header from `Request` or `Headers`
- run a route handler or server action inside `runWithRuntimeScenarioContext()`

```mermaid
flowchart LR
  subgraph C[Client or browser process]
    C1[request]
    C2[x-definitely-fine-scenario-id header]
  end

  subgraph N[Next.js server process]
    N1[@definitely-fine/nextjs wrapper]
    N2[runWithRuntimeScenarioContext]
    N3[definitely-fine runtime]
    N4[wrapped app service or function]
  end

  subgraph S[Shared scenario storage]
    S1[(persisted scenario JSON)]
  end

  C1 --> C2 --> N1
  N1 --> N2 --> N3 --> N4
  N3 -- load active scenario --> S1
```

## Route Handlers

Use `withDefinitelyFineScenario()` to wrap a route handler.

```ts
import { withDefinitelyFineScenario } from "@definitely-fine/nextjs";
import { incrementApiCounter } from "../lib/demo-runtime";

async function postCounterResponse(_request: Request): Promise<Response> {
  return Response.json(incrementApiCounter());
}

export const POST = withDefinitelyFineScenario(postCounterResponse);
```

If the request does not include the scenario header, the handler runs normally.

## Server Actions

Use `withDefinitelyFineServerAction()` to wrap a server action.

```ts
"use server";

import { withDefinitelyFineServerAction } from "@definitely-fine/nextjs";

import {
  incrementActionCounter,
  type CounterResult,
} from "../lib/demo-runtime";

export const incrementCounterAction = withDefinitelyFineServerAction(
  async function incrementCounterActionImplementation(
    _previousState: CounterResult,
  ): Promise<CounterResult> {
    return incrementActionCounter();
  },
);
```

## Header Name

The default exported header constant is `DEFINITELY_FINE_SCENARIO_HEADER`.

```ts
import { DEFINITELY_FINE_SCENARIO_HEADER } from "@definitely-fine/nextjs";

const headers = {
  [DEFINITELY_FINE_SCENARIO_HEADER]: "scenario-id",
};
```

## Typical Setup

1. Create and save a scenario with `definitely-fine`.
2. Wrap the relevant Next.js route handlers or server actions with this package.
3. Send the scenario id in the request header.
4. Let your core runtime wrappers decide which calls are intercepted.

For safety, production apps should normally disable the core runtime with `enabled: false` and optionally skip these wrappers entirely.

## With Playwright

This package pairs naturally with [`@definitely-fine/playwright`](../playwright/README.md), which can create browser contexts that already include the scenario header.