workflow 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/docs/advanced/dynamic-workflows.mdx +4 -1
  2. package/docs/advanced/index.mdx +13 -0
  3. package/docs/advanced/meta.json +5 -0
  4. package/docs/ai/chat-session-modeling.mdx +8 -8
  5. package/docs/ai/human-in-the-loop.mdx +7 -3
  6. package/docs/ai/index.mdx +14 -14
  7. package/docs/ai/streaming-updates-from-tools.mdx +2 -2
  8. package/docs/api-reference/vitest/index.mdx +2 -2
  9. package/docs/api-reference/workflow/create-hook.mdx +4 -0
  10. package/docs/api-reference/workflow/create-webhook.mdx +1 -1
  11. package/docs/api-reference/workflow/define-hook.mdx +4 -0
  12. package/docs/api-reference/workflow-api/get-hook-by-token.mdx +9 -3
  13. package/docs/api-reference/workflow-api/resume-hook.mdx +4 -0
  14. package/docs/api-reference/workflow-api/resume-webhook.mdx +4 -0
  15. package/docs/api-reference/workflow-globals.mdx +4 -0
  16. package/docs/api-reference/workflow-nest/index.mdx +4 -1
  17. package/docs/api-reference/workflow-nest/is-workflow-request.mdx +58 -0
  18. package/docs/api-reference/workflow-nest/meta.json +1 -0
  19. package/docs/api-reference/workflow-nest/workflow-controller.mdx +6 -2
  20. package/docs/api-reference/workflow-nest/workflow-module.mdx +9 -1
  21. package/docs/api-reference/workflow-runtime/world/storage.mdx +29 -0
  22. package/docs/configuration/build-and-diagnostics.mdx +11 -1
  23. package/docs/configuration/framework-options.mdx +6 -0
  24. package/docs/configuration/runtime-tuning.mdx +28 -2
  25. package/docs/configuration/worlds.mdx +28 -2
  26. package/docs/cookbook/common-patterns/webhooks.mdx +2 -1
  27. package/docs/cookbook/integrations/ai-sdk.mdx +8 -8
  28. package/docs/cookbook/integrations/chat-sdk.mdx +8 -8
  29. package/docs/cookbook/integrations/sandbox.mdx +8 -8
  30. package/docs/errors/node-js-module-in-workflow.mdx +36 -0
  31. package/docs/foundations/errors-and-retries.mdx +3 -3
  32. package/docs/foundations/hooks.mdx +91 -3
  33. package/docs/foundations/serialization.mdx +1 -1
  34. package/docs/foundations/streaming.mdx +1 -1
  35. package/docs/foundations/workflows-and-steps.mdx +1 -1
  36. package/docs/getting-started/astro.mdx +7 -9
  37. package/docs/getting-started/express.mdx +4 -10
  38. package/docs/getting-started/fastify.mdx +4 -9
  39. package/docs/getting-started/hono.mdx +4 -10
  40. package/docs/getting-started/index.mdx +2 -2
  41. package/docs/getting-started/nestjs.mdx +157 -36
  42. package/docs/getting-started/next.mdx +15 -18
  43. package/docs/getting-started/nitro.mdx +4 -10
  44. package/docs/getting-started/nuxt.mdx +4 -10
  45. package/docs/getting-started/react-router/v7.mdx +6 -22
  46. package/docs/getting-started/react-router/v8.mdx +6 -22
  47. package/docs/getting-started/sveltekit.mdx +7 -9
  48. package/docs/getting-started/tanstack-start.mdx +7 -9
  49. package/docs/getting-started/vite.mdx +7 -9
  50. package/docs/how-it-works/code-transform.mdx +13 -9
  51. package/docs/how-it-works/encryption.mdx +3 -1
  52. package/docs/meta.json +1 -1
  53. package/docs/testing/index.mdx +3 -5
  54. package/docs/whats-new.mdx +8 -2
  55. package/docs/worlds/building-a-world.mdx +68 -1
  56. package/docs/worlds/postgres.mdx +16 -32
  57. package/docs/worlds/upgrading-to-v5.mdx +29 -8
  58. package/docs/worlds/vercel.mdx +50 -4
  59. package/package.json +12 -12
@@ -16,7 +16,7 @@ related:
16
16
  Set up your first durable workflow in a NestJS app and learn the core Workflow SDK concepts.
17
17
 
18
18
  <Callout>
19
- NestJS integration is experimental. Deployment to Vercel is supported via the
19
+ NestJS integration is in beta. Deployment to Vercel is supported via the
20
20
  `workflow-nest build --vercel` command. See [Deploy to Vercel](#deploy-to-vercel) below.
21
21
  </Callout>
22
22
 
@@ -140,12 +140,9 @@ Add scripts to regenerate the SWC configuration before builds:
140
140
  }
141
141
  ```
142
142
 
143
- <Accordion type="single" collapsible>
144
- <AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
145
- <AccordionTrigger className="[&_p]:my-0 text-lg [&_p]:text-foreground">
146
- Set up IntelliSense for TypeScript (optional)
147
- </AccordionTrigger>
148
- <AccordionContent className="[&_p]:my-2">
143
+ <Details>
144
+ <Summary>Set up IntelliSense for TypeScript (optional)</Summary>
145
+
149
146
  To enable helpful hints in your IDE, set up the workflow plugin in `tsconfig.json`:
150
147
 
151
148
  ```json title="tsconfig.json" lineNumbers
@@ -161,10 +158,7 @@ To enable helpful hints in your IDE, set up the workflow plugin in `tsconfig.jso
161
158
  }
162
159
  ```
163
160
 
164
- </AccordionContent>
165
-
166
- </AccordionItem>
167
- </Accordion>
161
+ </Details>
168
162
 
169
163
  </Step>
170
164
 
@@ -384,10 +378,7 @@ import { AppModule } from '../dist/app.module.js';
384
378
  let ready: Promise<express.Express> | undefined;
385
379
 
386
380
  async function createHandler() {
387
- const app = await NestFactory.create<NestExpressApplication>(AppModule, {
388
- bodyParser: false,
389
- });
390
- app.use(express.json());
381
+ const app = await NestFactory.create<NestExpressApplication>(AppModule);
391
382
  await app.init();
392
383
  return app.getHttpAdapter().getInstance();
393
384
  }
@@ -416,6 +407,16 @@ Deploy as usual. `workflow-nest build --vercel` runs automatically on Vercel (it
416
407
  `VERCEL` environment variable), writing `.vercel/output` with the consumer function so your runs
417
408
  execute instead of staying `pending`.
418
409
 
410
+ <Callout type="info">
411
+ The app is bundled with esbuild. A package that resolves a dependency at runtime
412
+ behind a `try`/`catch` — a database driver reached through an ORM, an optional
413
+ logger transport — looks like a hard dependency to the bundler, which fails the
414
+ build on the first one your app has not installed. NestJS's own optional peers
415
+ are handled for you; pass anything else to `--external`, for example
416
+ `--external oracledb,mysql2`. Native addons (`*.node`) are not traced into the
417
+ deployed function and are reported as a build warning.
418
+ </Callout>
419
+
419
420
  </Step>
420
421
 
421
422
  </Steps>
@@ -473,6 +474,12 @@ WorkflowModule.forRoot({
473
474
  // (default: true, or false when VERCEL is set because dedicated functions
474
475
  // serve the bundles there).
475
476
  preloadBundles: true,
477
+
478
+ // Keep the application's body parser away from the workflow routes, so queue
479
+ // deliveries are not capped at Express's 100 KB limit and signed webhook
480
+ // bodies stay byte-exact (default: true). See "Request bodies and body
481
+ // parsers" below.
482
+ bypassBodyParser: true,
476
483
  });
477
484
  ```
478
485
 
@@ -521,41 +528,148 @@ function generates matching URLs:
521
528
  workflow-nest build --vercel --base-path /api
522
529
  ```
523
530
 
531
+ <Callout type="info">
532
+ `setGlobalPrefix(prefix, { exclude })` that excludes the workflow routes is
533
+ honoured too: they stay at the origin root, and the SDK generates unprefixed
534
+ URLs to match. `app.enableVersioning()` does not move them at all; see
535
+ [Route versioning](#route-versioning).
536
+ </Callout>
537
+
538
+ ---
539
+
540
+ ## Request bodies and body parsers
541
+
542
+ The workflow routes are a byte pipe, in both directions and at whatever size the
543
+ data happens to be:
544
+
545
+ - The queue delivers run inputs, step inputs and step outputs in the body of a
546
+ `POST /.well-known/workflow/v1/flow`. Express caps request bodies at 100 KB
547
+ and NestJS installs that parser by default, so a workflow that passes an array
548
+ of any size around would get `413 request entity too large` on every delivery,
549
+ with nothing but a retry loop to show for it.
550
+ - A webhook that verifies a signature over its raw body (Stripe, GitHub,
551
+ Shopify, Slack) only verifies if the bytes the sender signed arrive unchanged,
552
+ and a parser that has already turned the request into an object has destroyed
553
+ them.
554
+
555
+ `WorkflowModule` handles both by keeping the application's body parsers away
556
+ from `.well-known/workflow/v1`, and nothing else. On **Express**, workflow
557
+ requests are read straight from the request stream, so they are neither
558
+ size-limited nor re-serialized, and your own routes keep the parsers and limits
559
+ you configured. No bootstrap configuration is needed, and `{ rawBody: true }` is
560
+ not required for signed webhooks.
561
+
562
+ Set `bypassBodyParser: false` to opt out and handle parsing yourself.
563
+
524
564
  <Callout type="warn">
525
- `app.enableVersioning()` moves the workflow routes the same way, and is not
526
- handled automatically. Exclude the workflow controller from versioning, or mount
527
- it where the SDK expects it.
565
+ This stream bypass only applies to **uncompressed Express** requests. Two cases
566
+ fall back to re-serializing the parsed body with `JSON.stringify`, which does
567
+ **not** preserve whitespace or key order and therefore breaks webhook signature
568
+ verification (Stripe, GitHub, Shopify, Slack):
569
+
570
+ - **Fastify.** Fastify's content-type parser always consumes the request
571
+ stream before the route runs — `WorkflowModule` cannot stand it aside the way
572
+ it does Express's middleware — so the raw bytes are gone by the time the
573
+ handler sees them. Fastify's body limit is also enforced per instance rather
574
+ than per route; raise it on the adapter (for example
575
+ `new FastifyAdapter({ bodyLimit: 16 * 1024 * 1024 })`).
576
+ - **Compressed bodies.** A body that arrives with a `content-encoding` always
577
+ goes through the parser on Express too, because that is what inflates it.
578
+
579
+ For signed webhooks in either case, create the app with `{ rawBody: true }`
580
+ (`NestFactory.create(AppModule, new FastifyAdapter(), { rawBody: true })` on
581
+ Fastify) so the integration can recover the exact bytes the sender signed.
582
+ NestJS keeps them on `req.rawBody` on both platforms, so no extra plugin is
583
+ needed. Without it, the integration logs a one-time warning and falls back to
584
+ the lossy `JSON.stringify` path.
528
585
  </Callout>
529
586
 
587
+ <Callout type="info">
588
+ On Vercel the flow and webhook routes are served by their own Build Output
589
+ functions rather than by your NestJS app, so this only affects self-hosted
590
+ deployments.
591
+ </Callout>
592
+
593
+ ---
594
+
595
+ ## Guards, interceptors, and pipes
596
+
597
+ The workflow routes are served by a controller inside your application, so a
598
+ global guard runs for them too. A guard that rejects unauthenticated requests
599
+ rejects every queue delivery and webhook with `403`, and runs stop making
600
+ progress.
601
+
602
+ Exempt them with `isWorkflowRequest`:
603
+
604
+ {/*@skip-typecheck - Illustrates the pattern, not a complete app*/}
605
+
606
+ ```typescript
607
+ import { Injectable, type CanActivate, type ExecutionContext } from '@nestjs/common';
608
+ import { isWorkflowRequest } from 'workflow/nest';
609
+
610
+ @Injectable()
611
+ export class AuthGuard implements CanActivate {
612
+ canActivate(context: ExecutionContext) {
613
+ if (isWorkflowRequest(context)) return true;
614
+ // ...your own checks
615
+ }
616
+ }
617
+ ```
618
+
619
+ The workflow routes authenticate their own callers — queue deliveries are signed
620
+ and webhook tokens are single-use secrets — so letting them past an application
621
+ guard exposes nothing.
622
+
623
+ Interceptors and exception filters are safe to leave in place. The handlers
624
+ write through `@Res()`, so the exact status and body the workflow runtime
625
+ produced reach the caller, which is what the queue and third-party webhook
626
+ senders key off.
627
+
628
+ ---
629
+
630
+ ## Route versioning
631
+
632
+ `app.enableVersioning()` moves every route under a version segment. The workflow
633
+ controller is registered as `VERSION_NEUTRAL`, so it stays at
634
+ `.well-known/workflow/v1` whichever strategy you enable, and the URLs the SDK
635
+ generates keep resolving. A global prefix still applies on top, and is adopted
636
+ automatically.
637
+
530
638
  ---
531
639
 
532
- ## Raw request bodies
640
+ ## Fastify
533
641
 
534
- The workflow routes are a byte pipe. A webhook that verifies a signature over its
535
- raw body (Stripe, GitHub, Shopify, Slack) only works if the bytes the sender
536
- signed reach the workflow unchanged, and a body parser that has already turned
537
- the request into an object destroys them.
642
+ `@nestjs/platform-fastify` is supported alongside `@nestjs/platform-express`,
643
+ with two differences.
538
644
 
539
- Create the app with `rawBody` so the original bytes stay available:
645
+ Fastify enforces its body limit before any content-type parser runs, and the
646
+ limit is per instance rather than per route, so it cannot be scoped to the
647
+ workflow routes. Raise it on the adapter; `WorkflowModule` warns at startup
648
+ while it is still at Fastify's 1 MiB default:
540
649
 
541
650
  {/*@skip-typecheck - Bootstrap snippet*/}
542
651
 
543
652
  ```typescript
544
- const app = await NestFactory.create(AppModule, { rawBody: true });
653
+ const app = await NestFactory.create(
654
+ AppModule,
655
+ new FastifyAdapter({ bodyLimit: 16 * 1024 * 1024 })
656
+ );
545
657
  ```
546
658
 
547
- Without it, `@workflow/nest` falls back to re-serializing the parsed body with
548
- `JSON.stringify` and logs a warning once. That changes whitespace and key order,
549
- so signature verification fails.
659
+ Fastify also answers content types it has no parser for with `415` before the
660
+ request reaches a controller. Register a catch-all parser if your webhooks send
661
+ `application/octet-stream` or another unparsed media type:
550
662
 
551
- Content types no body parser claims (XML, `application/x-www-form-urlencoded`
552
- without the parser registered, custom media types) are read straight from the
553
- request stream and need no configuration.
663
+ {/*@skip-typecheck - Bootstrap snippet*/}
554
664
 
555
- <Callout type="info">
556
- On Vercel the webhook route is served by its own function rather than by your
557
- NestJS app, so this only affects self-hosted deployments.
558
- </Callout>
665
+ ```typescript
666
+ app
667
+ .getHttpAdapter()
668
+ .getInstance()
669
+ .addContentTypeParser('*', { parseAs: 'buffer' }, (_request, body, done) =>
670
+ done(null, body)
671
+ );
672
+ ```
559
673
 
560
674
  ---
561
675
 
@@ -631,11 +745,18 @@ plain functions so the intent is clear.
631
745
  leave `skipBuild` unset so the bundles are built during startup. With
632
746
  `skipBuild` set and no bundles present, startup fails with an explicit error
633
747
  rather than serving broken workflow routes.
634
- - Create the app with `{ rawBody: true }` if you receive signed webhooks.
748
+ - Exempt the workflow routes from any global guard with `isWorkflowRequest`, or
749
+ every queue delivery is rejected with `403`.
635
750
  - Set `basePath` (or rely on the adopted global prefix) so generated URLs match
636
751
  the routes NestJS serves.
637
752
  - Set `manageWorldLifecycle: true` for a self-hosted World, and call
638
753
  `app.enableShutdownHooks()` so the World is closed on a signal.
754
+ - On Fastify, raise the adapter's `bodyLimit` above the data your workflows pass
755
+ between steps.
756
+ - Install exactly one copy of `@nestjs/core`. With two, NestJS hands
757
+ `@workflow/nest` neither the global prefix nor the HTTP adapter, which
758
+ silently disables prefix handling and the body-parser bypass; a warning is
759
+ logged at startup when this happens.
639
760
  - `skipBuild` defaults to `true` when the `VERCEL` environment variable is set,
640
761
  so no Vercel-specific branch is needed in your module configuration.
641
762
 
@@ -52,12 +52,12 @@ const nextConfig: NextConfig = {
52
52
  export default withWorkflow(nextConfig); // [!code highlight]
53
53
  ```
54
54
 
55
- <Accordion type="single" collapsible>
56
- <AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
57
- <AccordionTrigger className="text-sm">
58
- ### Setup IntelliSense for TypeScript (Optional)
59
- </AccordionTrigger>
60
- <AccordionContent className="[&_p]:my-2">
55
+ <Details>
56
+ <Summary className="[&_h3]:my-0">
57
+
58
+ ### Setup IntelliSense for TypeScript (Optional)
59
+
60
+ </Summary>
61
61
 
62
62
  To enable helpful hints in your IDE, setup the workflow plugin in `tsconfig.json`:
63
63
 
@@ -74,16 +74,14 @@ To enable helpful hints in your IDE, setup the workflow plugin in `tsconfig.json
74
74
  }
75
75
  ```
76
76
 
77
- </AccordionContent>
78
- </AccordionItem>
79
- </Accordion>
77
+ </Details>
78
+
79
+ <Details>
80
+ <Summary className="[&_h3]:my-0">
80
81
 
81
- <Accordion type="single" collapsible>
82
- <AccordionItem value="configure-proxy-handler" className="[&_h3]:my-0">
83
- <AccordionTrigger className="text-sm">
84
- <h3 id="configure-proxy-handler">Configure Proxy Handler (if applicable)</h3>
85
- </AccordionTrigger>
86
- <AccordionContent className="[&_p]:my-2">
82
+ <h3 id="configure-proxy-handler" className="scroll-m-28">Configure Proxy Handler (if applicable)</h3>
83
+
84
+ </Summary>
87
85
 
88
86
  If your Next.js app has a [proxy handler](https://nextjs.org/docs/app/api-reference/file-conventions/proxy)
89
87
  (formerly known as "middleware"), you'll need to update the matcher pattern to exclude Workflow's
@@ -113,9 +111,8 @@ export const config = {
113
111
  ```
114
112
 
115
113
  This ensures that internal Workflow paths are not intercepted by your middleware, which could interfere with workflow execution and resumption.
116
- </AccordionContent>
117
- </AccordionItem>
118
- </Accordion>
114
+
115
+ </Details>
119
116
 
120
117
  </Step>
121
118
 
@@ -72,12 +72,9 @@ export default defineConfig({
72
72
  | `runtime` | `string` | `'nodejs22.x'` | Node.js runtime version for Vercel Functions (e.g. `'nodejs22.x'`, `'nodejs24.x'`). |
73
73
  | `sourcemap` | `boolean \| 'inline' \| 'linked' \| 'external' \| 'both'` | `'inline'` (dev) / `false` (prod) | Controls source maps on generated workflow bundles. Accepts the same values as esbuild's `sourcemap` option. Defaults to `'inline'` in development and `false` in production (smaller function bundles, which helps stay under the Vercel 250 MB function size limit). Set it explicitly, or use the `WORKFLOW_SOURCEMAP` environment variable, to override in either environment. |
74
74
 
75
- <Accordion type="single" collapsible>
76
- <AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
77
- <AccordionTrigger className="[&_p]:my-0 text-lg [&_p]:text-foreground">
78
- Set up IntelliSense for TypeScript (optional)
79
- </AccordionTrigger>
80
- <AccordionContent className="[&_p]:my-2">
75
+ <Details>
76
+ <Summary>Set up IntelliSense for TypeScript (optional)</Summary>
77
+
81
78
  To enable helpful hints in your IDE, set up the workflow plugin in `tsconfig.json`:
82
79
 
83
80
  ```json title="tsconfig.json" lineNumbers
@@ -93,10 +90,7 @@ To enable helpful hints in your IDE, set up the workflow plugin in `tsconfig.jso
93
90
  }
94
91
  ```
95
92
 
96
- </AccordionContent>
97
-
98
- </AccordionItem>
99
- </Accordion>
93
+ </Details>
100
94
 
101
95
  </Step>
102
96
 
@@ -51,12 +51,9 @@ export default defineNuxtConfig({
51
51
 
52
52
  This will also automatically enable the TypeScript plugin, which provides helpful IntelliSense hints in your IDE for workflow and step functions.
53
53
 
54
- <Accordion type="single" collapsible>
55
- <AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
56
- <AccordionTrigger className="[&_p]:my-0 text-lg [&_p]:text-foreground">
57
- Disable TypeScript Plugin (Optional)
58
- </AccordionTrigger>
59
- <AccordionContent className="[&_p]:my-2">
54
+ <Details>
55
+ <Summary>Disable TypeScript Plugin (Optional)</Summary>
56
+
60
57
  The TypeScript plugin is enabled by default. If you need to disable it, you can configure it in your `nuxt.config.ts`:
61
58
 
62
59
  {/* @skip-typecheck: incomplete code sample */}
@@ -70,10 +67,7 @@ export default defineNuxtConfig({
70
67
  });
71
68
  ```
72
69
 
73
- </AccordionContent>
74
-
75
- </AccordionItem>
76
- </Accordion>
70
+ </Details>
77
71
 
78
72
  </Step>
79
73
 
@@ -18,41 +18,25 @@ This guide starts with an existing React Router v7 framework-mode app. It is ver
18
18
 
19
19
  ## Install Nitro and Workflow SDK
20
20
 
21
- <Tabs items={["npm", "pnpm", "bun", "yarn"]} defaultValue="pnpm">
21
+ <CodeBlockTabs defaultValue="pnpm">
22
22
 
23
- <Tab value="npm">
24
-
25
- ```bash
23
+ ```bash tab="npm"
26
24
  npm install nitro workflow
27
25
  ```
28
26
 
29
- </Tab>
30
-
31
- <Tab value="pnpm">
32
-
33
- ```bash
27
+ ```bash tab="pnpm"
34
28
  pnpm add nitro workflow
35
29
  ```
36
30
 
37
- </Tab>
38
-
39
- <Tab value="bun">
40
-
41
- ```bash
31
+ ```bash tab="bun"
42
32
  bun add nitro workflow
43
33
  ```
44
34
 
45
- </Tab>
46
-
47
- <Tab value="yarn">
48
-
49
- ```bash
35
+ ```bash tab="yarn"
50
36
  yarn add nitro workflow
51
37
  ```
52
38
 
53
- </Tab>
54
-
55
- </Tabs>
39
+ </CodeBlockTabs>
56
40
 
57
41
  This integration requires Nitro v3.
58
42
 
@@ -18,41 +18,25 @@ This guide starts with an existing React Router v8 framework-mode app.
18
18
 
19
19
  ## Install Nitro and Workflow SDK
20
20
 
21
- <Tabs items={["npm", "pnpm", "bun", "yarn"]} defaultValue="pnpm">
21
+ <CodeBlockTabs defaultValue="pnpm">
22
22
 
23
- <Tab value="npm">
24
-
25
- ```bash
23
+ ```bash tab="npm"
26
24
  npm install nitro workflow
27
25
  ```
28
26
 
29
- </Tab>
30
-
31
- <Tab value="pnpm">
32
-
33
- ```bash
27
+ ```bash tab="pnpm"
34
28
  pnpm add nitro workflow
35
29
  ```
36
30
 
37
- </Tab>
38
-
39
- <Tab value="bun">
40
-
41
- ```bash
31
+ ```bash tab="bun"
42
32
  bun add nitro workflow
43
33
  ```
44
34
 
45
- </Tab>
46
-
47
- <Tab value="yarn">
48
-
49
- ```bash
35
+ ```bash tab="yarn"
50
36
  yarn add nitro workflow
51
37
  ```
52
38
 
53
- </Tab>
54
-
55
- </Tabs>
39
+ </CodeBlockTabs>
56
40
 
57
41
  This integration requires Nitro v3.
58
42
 
@@ -56,12 +56,12 @@ export default defineConfig({
56
56
  | --- | --- | --- | --- |
57
57
  | `sourcemap` | `boolean \| 'inline' \| 'linked' \| 'external' \| 'both'` | `'inline'` (dev) / `false` (prod) | Controls source maps on generated workflow bundles. Accepts the same values as esbuild's `sourcemap` option. Defaults to `'inline'` in development and `false` in production (smaller function bundles, which helps stay under the Vercel 250 MB function size limit). Set it explicitly, or use the `WORKFLOW_SOURCEMAP` environment variable, to override in either environment. |
58
58
 
59
- <Accordion type="single" collapsible>
60
- <AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
61
- <AccordionTrigger className="text-sm">
62
- ### Set up IntelliSense for TypeScript (optional)
63
- </AccordionTrigger>
64
- <AccordionContent className="[&_p]:my-2">
59
+ <Details>
60
+ <Summary className="[&_h3]:my-0">
61
+
62
+ ### Set up IntelliSense for TypeScript (optional)
63
+
64
+ </Summary>
65
65
 
66
66
  To enable helpful hints in your IDE, set up the workflow plugin in `tsconfig.json`:
67
67
 
@@ -78,9 +78,7 @@ To enable helpful hints in your IDE, set up the workflow plugin in `tsconfig.jso
78
78
  }
79
79
  ```
80
80
 
81
- </AccordionContent>
82
- </AccordionItem>
83
- </Accordion>
81
+ </Details>
84
82
 
85
83
  </Step>
86
84
 
@@ -57,12 +57,12 @@ export default defineConfig({
57
57
  });
58
58
  ```
59
59
 
60
- <Accordion type="single" collapsible>
61
- <AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
62
- <AccordionTrigger className="text-sm">
63
- ### Set up IntelliSense for TypeScript (optional)
64
- </AccordionTrigger>
65
- <AccordionContent className="[&_p]:my-2">
60
+ <Details>
61
+ <Summary className="[&_h3]:my-0">
62
+
63
+ ### Set up IntelliSense for TypeScript (optional)
64
+
65
+ </Summary>
66
66
 
67
67
  To enable helpful hints in your IDE, set up the workflow plugin in `tsconfig.json`:
68
68
 
@@ -79,9 +79,7 @@ To enable helpful hints in your IDE, set up the workflow plugin in `tsconfig.jso
79
79
  }
80
80
  ```
81
81
 
82
- </AccordionContent>
83
- </AccordionItem>
84
- </Accordion>
82
+ </Details>
85
83
 
86
84
  </Step>
87
85
 
@@ -61,12 +61,12 @@ export default defineConfig({
61
61
  });
62
62
  ```
63
63
 
64
- <Accordion type="single" collapsible>
65
- <AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
66
- <AccordionTrigger className="text-sm">
67
- ### Setup IntelliSense for TypeScript (Optional)
68
- </AccordionTrigger>
69
- <AccordionContent className="[&_p]:my-2">
64
+ <Details>
65
+ <Summary className="[&_h3]:my-0">
66
+
67
+ ### Setup IntelliSense for TypeScript (Optional)
68
+
69
+ </Summary>
70
70
 
71
71
  To enable helpful hints in your IDE, setup the workflow plugin in `tsconfig.json`:
72
72
 
@@ -83,9 +83,7 @@ To enable helpful hints in your IDE, setup the workflow plugin in `tsconfig.json
83
83
  }
84
84
  ```
85
85
 
86
- </AccordionContent>
87
- </AccordionItem>
88
- </Accordion>
86
+ </Details>
89
87
 
90
88
  </Step>
91
89
 
@@ -74,8 +74,9 @@ flowchart LR
74
74
 
75
75
  ## Detailed transformation examples
76
76
 
77
- <Tabs items={["Step Mode", "Workflow Mode", "Detect Mode"]}>
78
- <Tab value="Step Mode">
77
+ <TabsWithChildren tabs={["Step Mode","Workflow Mode","Detect Mode"]}>
78
+
79
+ <TabContent order={1}>
79
80
 
80
81
  **Step Mode** creates the registration bundle that the combined flow handler imports (it is not an HTTP route), and is also the transform framework loaders apply to your application code.
81
82
 
@@ -126,8 +127,9 @@ handleUserSignup.workflowId = "workflow//workflows/user.js//handleUserSignup"; /
126
127
 
127
128
  **ID format:** Step IDs follow the pattern `step//{filepath}//{functionName}`, where the file path is relative to your project root.
128
129
 
129
- </Tab>
130
- <Tab value="Workflow Mode">
130
+ </TabContent>
131
+
132
+ <TabContent order={2}>
131
133
 
132
134
  **Workflow Mode** creates the workflow execution bundle served at `/.well-known/workflow/v1/flow`.
133
135
 
@@ -176,8 +178,9 @@ handleUserSignup.workflowId = "workflow//workflows/user.js//handleUserSignup"; /
176
178
 
177
179
  **ID format:** Workflow IDs follow the pattern `workflow//{filepath}//{functionName}`. The `workflowId` property is attached to the function so [`start()`](/docs/api-reference/workflow-api/start) works at runtime.
178
180
 
179
- </Tab>
180
- <Tab value="Detect Mode">
181
+ </TabContent>
182
+
183
+ <TabContent order={3}>
181
184
 
182
185
  **Detect Mode** is a lightweight, non-transforming mode used during the build's discovery phase.
183
186
 
@@ -216,8 +219,9 @@ export async function handleUserSignup(email: string) {
216
219
  **Working without the app-code loader:** Frameworks apply the step-mode transform to application code by default, which is what gives `start(handleUserSignup)` its automatic IDs and type safety. If your setup can't run the loader, you can instead construct workflow IDs manually using the pattern `workflow//{filepath}//{functionName}`, look them up in the build manifest, and pass them to `start()` as strings.
217
220
  </Callout>
218
221
 
219
- </Tab>
220
- </Tabs>
222
+ </TabContent>
223
+
224
+ </TabsWithChildren>
221
225
 
222
226
  ## Generated files
223
227
 
@@ -268,7 +272,7 @@ Contains all step functions transformed in **step mode**. The combined flow hand
268
272
  This module must not be exposed as an HTTP endpoint.
269
273
 
270
274
  <Callout type="info">
271
- **Changed in 5.0:** In 4.x, the step bundle was served as its own HTTP route at `POST /.well-known/workflow/v1/step`, with step messages delivered on a separate `__wkf_step_*` queue topic. v5 merged both into the combined flow handler. The step bundle became a registration module imported by `flow.js`, and step messages arrive on the shared workflow queue. Use the version picker to see the old layout on the v4 version of this page.
275
+ **Changed in 5.0:** In 4.x, the step bundle was served as its own HTTP route at `POST /.well-known/workflow/v1/step`, with step messages delivered on a separate `__wkf_step_*` queue topic. v5 merged both into the combined flow handler. The step bundle became a registration module imported by `flow.js`, and step messages arrive on the shared workflow queue. See the [v4 version of this page](/v4/docs/how-it-works/code-transform) for the old layout.
272
276
  </Callout>
273
277
 
274
278
  ### `webhook.js`
@@ -36,7 +36,9 @@ Metadata such as workflow names, step names, entity IDs, timestamps, and lifecyc
36
36
 
37
37
  ### Compression
38
38
 
39
- Payloads are compressed before encryption. A format prefix on the stored value records the compression codec (gzip, with zstd support in the format), and the inner payload keeps its own serialization format prefix after decompression. Repetitive payloads compress heavily. AI token streams average around 80% smaller, reducing storage and network transfer. Like encryption, compression is automatic and requires no code changes.
39
+ Payloads are compressed before encryption. A format prefix on the stored value records the compression codec, and the inner payload keeps its own serialization format prefix after decompression. Repetitive payloads compress heavily. AI token streams average around 80% smaller, reducing storage and network transfer. Like encryption, compression is automatic and requires no code changes.
40
+
41
+ The codec is zstd when both the writer and the run's deployment run Node.js 22.15+ (or 23.8+), and gzip otherwise. Runs started on an older Node.js version stay readable after you upgrade the project's Node.js version. To force a codec, set [`WORKFLOW_COMPRESSION_CODEC`](/docs/configuration/runtime-tuning#workflow_compression_codec).
40
42
 
41
43
  ### Key management
42
44
 
package/docs/meta.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "getting-started",
6
6
  "foundations",
7
7
  "how-it-works",
8
- "advanced/dynamic-workflows",
8
+ "advanced",
9
9
  "observability",
10
10
  "ai",
11
11
  "testing",