Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,75 @@ compiler. Remove that package from `serverExternalPackages` in your
`next.config` to silence the warning.
</Callout>

### Workflow Discovery in Next.js

`withWorkflow()` discovers workflow entrypoints from `start()` calls imported
from `workflow/api` in your Next.js server files. In App Router projects, that
usually means files under `app/` or `src/app/`, such as Route Handlers, pages,
or layouts. In Pages Router projects, files under `pages/` or `src/pages/` are
scanned.

The `start()` call must be statically reachable from one of those Next.js
entries so the compiler can find the workflow function and transform any
`"use workflow"` and `"use step"` directives it imports.

```typescript title="app/api/signup/route.ts" lineNumbers
import { start } from "workflow/api";
import { handleUserSignup } from "@/workflows/user-signup";

export async function POST(request: Request) {
const { email } = await request.json();

await start(handleUserSignup, [email]);

return Response.json({ ok: true });
}
```

<Callout type="info">
Use `start()` in normal server-side entrypoints, including Route Handlers and
Server Actions. Do not call workflow functions directly from those entrypoints;
direct invocation bypasses the workflow runtime.
</Callout>

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

Keep top-level `"use server"` directives on files that define Server Action
entrypoints. Do not put a top-level `"use server"` directive in modules that are
imported by workflow or step functions.

Workflow bundles wrap imported modules during transformation. When a bundled
module contains a top-level `"use server"` directive, Next.js can treat the
generated wrapper as a Server Action module and fail validation with errors such
as `Server Actions must be async functions`.

Split Server Action wrappers from reusable workflow logic:

```typescript title="app/actions.ts" lineNumbers
"use server";

import { start } from "workflow/api";
import { processSignup } from "@/workflows/signup";

export async function signupAction(email: string) {
await start(processSignup, [email]);
}
```

```typescript title="workflows/signup.ts" lineNumbers
export async function processSignup(email: string) {
"use workflow";

await createUser(email);
}

async function createUser(email: string) {
"use step";

return { email };
}
```

### 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:
Expand Down