---
title: withWorkflow
description: Configure webpack/turbopack to transform workflow directives in Next.js.
type: reference
summary: Wrap your Next.js config with withWorkflow to enable workflow directive transformation.
prerequisites:
  - /docs/getting-started/next
---

Configures webpack/turbopack loaders to transform workflow code (`"use step"`/`"use workflow"` directives)

## Usage

To enable `"use step"` and `"use workflow"` directives while developing locally or deploying to production, wrap your `nextConfig` with `withWorkflow`.

```typescript title="next.config.ts" lineNumbers
import { withWorkflow } from "workflow/next"; // [!code highlight]
import type { NextConfig } from "next";
 
const nextConfig: NextConfig = {
  // … rest of your Next.js config
};

// not required but allows configuring workflow options
const workflowConfig = {} 

export default withWorkflow(nextConfig, workflowConfig); // [!code highlight]
```

<Callout type="warn">
If a package in `serverExternalPackages` contains workflow code (`"use step"`,
`"use workflow"`, or serialization classes), `withWorkflow()` automatically
removes it from `serverExternalPackages` for the current build and prints a
warning. Workflow still compiles the package so its directives are transformed.
Remove that package from `serverExternalPackages` in your
`next.config` to silence the warning.
</Callout>

### Workflow Discovery in Next.js

`withWorkflow()` discovers workflows by scanning your Next.js entrypoints — App
Router `route`, `page`, and `layout` files (under `app/` or `src/app/`) and any
file under `pages/` or `src/pages/` — for `start()` calls imported from
`workflow/api`. The workflow and step files themselves can live anywhere (for
example `src/workflows/`); they are discovered transitively through imports, as
long as a `start()` call in an entrypoint statically reaches them.

<Callout type="info">
Call `start()` from server-side entrypoints, including Route Handlers and Server
Actions. Don't call workflow functions directly — that bypasses the workflow
runtime.
</Callout>

### Next.js Server Actions and `"use server"`

Don't put a top-level `"use server"` directive in modules imported by workflow
or step functions. Workflow transformation wraps imported modules in synchronous
initializers, and Next.js rejects a `"use server"` directive inside that wrapper
with errors like `Server Actions must be async functions`. Keep `"use server"`
on the files that define your Server Actions, and move shared logic into
separate modules that don't carry the directive.

### Monorepos and Workspace Imports

By default, Next.js detects the correct workspace root automatically. If your Next.js app lives in a subdirectory such as `apps/web` and workspace resolution is not working correctly, you can set `outputFileTracingRoot` as a workaround:

```typescript title="apps/web/next.config.ts" lineNumbers
import { resolve } from "node:path";
import type { NextConfig } from "next";
import { withWorkflow } from "workflow/next";

const nextConfig: NextConfig = {
  outputFileTracingRoot: resolve(process.cwd(), "../.."),
};

export default withWorkflow(nextConfig);
```

<Callout type="info">
Use the smallest directory that contains every workspace package imported by your workflows. If your app already lives at the repository root, you do not need to set `outputFileTracingRoot`.
</Callout>

## Options

`withWorkflow` accepts an optional second argument to configure the Next.js integration.

```typescript title="next.config.ts" lineNumbers
import type { NextConfig } from "next";
import { withWorkflow } from "workflow/next";

const nextConfig: NextConfig = {};

export default withWorkflow(nextConfig, {
  workflows: {
    local: {
      port: 4000,
    },
  },
});
```

| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `workflows.local.port` | `number` | — | Overrides the `PORT` environment variable for local development. Has no effect when deployed to Vercel. |

<Callout type="info">
The `workflows.local` options only affect local development. When deployed to Vercel, the runtime ignores `local` settings and uses the Vercel world automatically.
</Callout>

## Exporting a Function


If you are exporting a function in your `next.config` you will need to ensure you call the function returned from `withWorkflow`.

```typescript title="next.config.ts" lineNumbers
import { NextConfig } from "next";
import { withWorkflow } from "workflow/next";
import createNextIntlPlugin from "next-intl/plugin";

const withNextIntl = createNextIntlPlugin();

export default async function config(
  phase: string,
  ctx: {
    defaultConfig: NextConfig
  }
): Promise<NextConfig> {
  let nextConfig: NextConfig | typeof config = {};

  for (const configModifier of [withNextIntl, withWorkflow]) {
    nextConfig = configModifier(nextConfig);

    if (typeof nextConfig === "function") {
      nextConfig = await nextConfig(phase, ctx);
    }
  }
  return nextConfig;
}
``` 
