From c38975e0962aa7a687414dda5daa85c63708018e Mon Sep 17 00:00:00 2001 From: Clay Levering Date: Tue, 16 Dec 2025 08:02:15 -0800 Subject: [PATCH 1/5] Enables local queue origin config via Nitro runtime Allows configuring the local world queue origin using Nitro's runtime config. This enables users to specify custom domains, ports, or environments via runtime config, especially useful in Nuxt applications. It adds a Nitro plugin that maps runtime config to the `WORKFLOW_LOCAL_BASE_URL` environment variable. Also, improves local world config to prioritize the `WORKFLOW_LOCAL_BASE_URL` environment variable. --- .../docs/deploying/world/local-world.mdx | 4 ++ docs/content/docs/getting-started/nuxt.mdx | 25 +++++++++ packages/nitro/src/index.ts | 11 ++++ .../src/runtime/workflow-runtime-config.ts | 55 +++++++++++++++++++ packages/world-local/src/config.ts | 8 ++- 5 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 packages/nitro/src/runtime/workflow-runtime-config.ts diff --git a/docs/content/docs/deploying/world/local-world.mdx b/docs/content/docs/deploying/world/local-world.mdx index 0ce73609b..8c115c17b 100644 --- a/docs/content/docs/deploying/world/local-world.mdx +++ b/docs/content/docs/deploying/world/local-world.mdx @@ -114,6 +114,10 @@ For advanced use cases like HTTPS or custom hostnames, you can override the enti export WORKFLOW_LOCAL_BASE_URL=https://local.example.com:3000 ``` +**Nuxt / Nitro runtime config (optional):** + +If you're using Nuxt (or Nitro directly), configure the origin via runtime config and let the `workflow/nitro` module map it to `WORKFLOW_LOCAL_BASE_URL` internally at runtime. + **Programmatically:** ```typescript diff --git a/docs/content/docs/getting-started/nuxt.mdx b/docs/content/docs/getting-started/nuxt.mdx index 35d948ce8..cc57ef0f7 100644 --- a/docs/content/docs/getting-started/nuxt.mdx +++ b/docs/content/docs/getting-started/nuxt.mdx @@ -214,6 +214,31 @@ npx workflow inspect runs +## Custom domains / ports (Nuxt runtime config) + +If you're running Nuxt behind a reverse proxy, tunnel, custom hostname, or non-standard port, configure the local world queue origin using Nuxt `runtimeConfig`. + +Add this to your `nuxt.config.ts`: + +```typescript title="nuxt.config.ts" lineNumbers +export default defineNuxtConfig({ + modules: ["workflow/nuxt"], + runtimeConfig: { + // Server-only (recommended): this is internal queue traffic, not browser config. + workflow: { + // Full origin (recommended) + baseUrl: "https://local.example.com:4443", + // Or build it from parts: + // protocol: "https", + // host: "local.example.com", + // port: 4443, + }, + }, +}); +``` + +This works because Nuxt exposes runtime config via `useRuntimeConfig()` on the server, and the `workflow/nitro` integration uses it to set `WORKFLOW_LOCAL_BASE_URL` for local queue traffic. See Nuxt docs: `https://nuxt.com/docs/4.x/guide/going-further/runtime-config`. + ## Deploying to production Workflow DevKit apps currently work best when deployed to [Vercel](https://vercel.com/home) and needs no special configuration. diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 33e6e67f4..9bd955304 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1,4 +1,5 @@ import type { Nitro, NitroModule, RollupConfig } from 'nitro/types'; +import { fileURLToPath } from 'node:url'; import { join } from 'pathe'; import { LocalBuilder, VercelBuilder } from './builders.js'; import { workflowTransformPlugin } from '@workflow/rollup'; @@ -12,6 +13,16 @@ export default { const isVercelDeploy = !nitro.options.dev && nitro.options.preset === 'vercel'; + // Runtime plugin: allow configuring local queue origin via Nitro runtimeConfig + // (Nuxt feeds its runtimeConfig into Nitro, so this enables Nuxt runtimeConfig support too.) + nitro.options.plugins ||= []; + const runtimePluginPath = fileURLToPath( + new URL('./runtime/workflow-runtime-config', import.meta.url) + ); + if (!nitro.options.plugins.includes(runtimePluginPath)) { + nitro.options.plugins.push(runtimePluginPath); + } + // Add transform plugin nitro.hooks.hook('rollup:before', (_nitro: Nitro, config: RollupConfig) => { (config.plugins as Array).push(workflowTransformPlugin()); diff --git a/packages/nitro/src/runtime/workflow-runtime-config.ts b/packages/nitro/src/runtime/workflow-runtime-config.ts new file mode 100644 index 000000000..c8dadcc7e --- /dev/null +++ b/packages/nitro/src/runtime/workflow-runtime-config.ts @@ -0,0 +1,55 @@ +import { defineNitroPlugin } from 'nitro/~internal/runtime/plugin'; +import { useRuntimeConfig } from 'nitro/runtime-config'; + +/** + * Bridge Nitro runtimeConfig -> Workflow local world env vars. + * + * This is framework-agnostic: + * - Works in Nuxt because Nuxt feeds runtimeConfig into Nitro. + * - Works in standalone Nitro if the user provides `runtimeConfig` in nitro.config. + * + * Supported keys: + * - `runtimeConfig.workflow.baseUrl` (preferred, private/server-only) + * - `runtimeConfig.public.workflow.baseUrl` (fallback) + * - `runtimeConfig.workflow.{protocol,host,port}` (preferred) + * - `runtimeConfig.public.workflow.{protocol,host,port}` (fallback) + * + * Result: + * - Sets `process.env.WORKFLOW_LOCAL_BASE_URL` if not already set. + */ +export default defineNitroPlugin(() => { + if (process.env.WORKFLOW_LOCAL_BASE_URL) return; + + const runtimeConfig = useRuntimeConfig() as any; + const workflow = + runtimeConfig?.workflow ?? + runtimeConfig?.public?.workflow ?? + (undefined as any); + + if (!workflow) return; + + // Full baseUrl override (recommended) + if (typeof workflow.baseUrl === 'string' && workflow.baseUrl.length > 0) { + process.env.WORKFLOW_LOCAL_BASE_URL = workflow.baseUrl; + return; + } + + // Construct from parts (protocol/host/port) + const protocol = + typeof workflow.protocol === 'string' && workflow.protocol.length > 0 + ? workflow.protocol + : undefined; + const host = + typeof workflow.host === 'string' && workflow.host.length > 0 + ? workflow.host + : undefined; + const port = + typeof workflow.port === 'number' || typeof workflow.port === 'string' + ? String(workflow.port) + : undefined; + + if (!protocol || !host) return; + process.env.WORKFLOW_LOCAL_BASE_URL = port + ? `${protocol}://${host}:${port}` + : `${protocol}://${host}`; +}); diff --git a/packages/world-local/src/config.ts b/packages/world-local/src/config.ts index dfd4e1557..d06084e58 100644 --- a/packages/world-local/src/config.ts +++ b/packages/world-local/src/config.ts @@ -8,6 +8,7 @@ const getDataDirFromEnv = () => { export const DEFAULT_RESOLVE_DATA_OPTION = 'all'; const getBaseUrlFromEnv = () => { + // Primary Workflow env var (documented) return process.env.WORKFLOW_LOCAL_BASE_URL; }; @@ -32,8 +33,11 @@ export const config = once(() => { * 4. Auto-detected port via getPort (detect actual listening port) */ export async function resolveBaseUrl(config: Partial): Promise { - if (config.baseUrl) { - return config.baseUrl; + // Allow resolving from env even if caller didn't pass merged config. + // (createLocalWorld() merges env config, but some callers use resolveBaseUrl directly.) + const envBaseUrl = getBaseUrlFromEnv(); + if (config.baseUrl || envBaseUrl) { + return config.baseUrl ?? envBaseUrl!; } if (typeof config.port === 'number') { From 4e55b9944a6b45337f8c14f645d5fc9503fccfb8 Mon Sep 17 00:00:00 2001 From: Clay Levering Date: Tue, 16 Dec 2025 08:09:34 -0800 Subject: [PATCH 2/5] Small change to wording --- docs/content/docs/getting-started/nuxt.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/getting-started/nuxt.mdx b/docs/content/docs/getting-started/nuxt.mdx index cc57ef0f7..b41ed539a 100644 --- a/docs/content/docs/getting-started/nuxt.mdx +++ b/docs/content/docs/getting-started/nuxt.mdx @@ -224,7 +224,7 @@ Add this to your `nuxt.config.ts`: export default defineNuxtConfig({ modules: ["workflow/nuxt"], runtimeConfig: { - // Server-only (recommended): this is internal queue traffic, not browser config. + // Server-only runtime config: this is internal queue traffic, not for the browser. workflow: { // Full origin (recommended) baseUrl: "https://local.example.com:4443", From 5544d0952956500f3f8f14188935db4cfbdddcc3 Mon Sep 17 00:00:00 2001 From: Clay Levering Date: Tue, 16 Dec 2025 08:39:51 -0800 Subject: [PATCH 3/5] Adds changeset for version bump --- .changeset/nitro-local-queue-origin.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/nitro-local-queue-origin.md diff --git a/.changeset/nitro-local-queue-origin.md b/.changeset/nitro-local-queue-origin.md new file mode 100644 index 000000000..366a6e720 --- /dev/null +++ b/.changeset/nitro-local-queue-origin.md @@ -0,0 +1,9 @@ +--- +"@workflow/nitro": patch +"@workflow/nuxt": patch +"@workflow/world-local": patch +--- + +Enables local queue origin config via Nitro runtime. + + From 94e156a1b16f0ccbdc44eab07f080a97a9baadeb Mon Sep 17 00:00:00 2001 From: Clay Levering Date: Tue, 16 Dec 2025 13:42:58 -0800 Subject: [PATCH 4/5] Consolidates Nuxt runtime config documentation Moves Nuxt runtime config documentation to the local world deployment guide and removes the duplicate from getting started as it is an advanced topic. Great feedback from @adriandlam This change centralizes the information and avoids repetition. --- .../docs/deploying/world/local-world.mdx | 21 +++++++++++++++- docs/content/docs/getting-started/nuxt.mdx | 25 ------------------- .../src/runtime/workflow-runtime-config.ts | 6 ++--- 3 files changed, 22 insertions(+), 30 deletions(-) diff --git a/docs/content/docs/deploying/world/local-world.mdx b/docs/content/docs/deploying/world/local-world.mdx index 8c115c17b..dedfb7360 100644 --- a/docs/content/docs/deploying/world/local-world.mdx +++ b/docs/content/docs/deploying/world/local-world.mdx @@ -116,7 +116,26 @@ export WORKFLOW_LOCAL_BASE_URL=https://local.example.com:3000 **Nuxt / Nitro runtime config (optional):** -If you're using Nuxt (or Nitro directly), configure the origin via runtime config and let the `workflow/nitro` module map it to `WORKFLOW_LOCAL_BASE_URL` internally at runtime. +If you're using Nuxt / Nitro and are running your app behind a reverse proxy, tunnel, custom hostname, or non-standard port, configure the origin via runtime config. Add this to your `nuxt.config.ts`: + +```typescript title="nuxt.config.ts" lineNumbers +export default defineNuxtConfig({ + modules: ["workflow/nuxt"], + runtimeConfig: { + // Server-only runtime config: this is internal queue traffic, not for the browser. + workflow: { + // Full origin (recommended) + baseUrl: "https://local.example.com:4443", + // Or build it from parts: + // protocol: "https", + // host: "local.example.com", + // port: 4443, + }, + }, +}); +``` + +This works because Nuxt exposes runtime config via `useRuntimeConfig()` on the server, and the `workflow/nitro` integration uses it to set `WORKFLOW_LOCAL_BASE_URL` for local queue traffic. See Nuxt docs: `https://nuxt.com/docs/4.x/guide/going-further/runtime-config`. **Programmatically:** diff --git a/docs/content/docs/getting-started/nuxt.mdx b/docs/content/docs/getting-started/nuxt.mdx index b41ed539a..35d948ce8 100644 --- a/docs/content/docs/getting-started/nuxt.mdx +++ b/docs/content/docs/getting-started/nuxt.mdx @@ -214,31 +214,6 @@ npx workflow inspect runs -## Custom domains / ports (Nuxt runtime config) - -If you're running Nuxt behind a reverse proxy, tunnel, custom hostname, or non-standard port, configure the local world queue origin using Nuxt `runtimeConfig`. - -Add this to your `nuxt.config.ts`: - -```typescript title="nuxt.config.ts" lineNumbers -export default defineNuxtConfig({ - modules: ["workflow/nuxt"], - runtimeConfig: { - // Server-only runtime config: this is internal queue traffic, not for the browser. - workflow: { - // Full origin (recommended) - baseUrl: "https://local.example.com:4443", - // Or build it from parts: - // protocol: "https", - // host: "local.example.com", - // port: 4443, - }, - }, -}); -``` - -This works because Nuxt exposes runtime config via `useRuntimeConfig()` on the server, and the `workflow/nitro` integration uses it to set `WORKFLOW_LOCAL_BASE_URL` for local queue traffic. See Nuxt docs: `https://nuxt.com/docs/4.x/guide/going-further/runtime-config`. - ## Deploying to production Workflow DevKit apps currently work best when deployed to [Vercel](https://vercel.com/home) and needs no special configuration. diff --git a/packages/nitro/src/runtime/workflow-runtime-config.ts b/packages/nitro/src/runtime/workflow-runtime-config.ts index c8dadcc7e..828346ab5 100644 --- a/packages/nitro/src/runtime/workflow-runtime-config.ts +++ b/packages/nitro/src/runtime/workflow-runtime-config.ts @@ -20,11 +20,9 @@ import { useRuntimeConfig } from 'nitro/runtime-config'; export default defineNitroPlugin(() => { if (process.env.WORKFLOW_LOCAL_BASE_URL) return; - const runtimeConfig = useRuntimeConfig() as any; + const runtimeConfig = useRuntimeConfig(); const workflow = - runtimeConfig?.workflow ?? - runtimeConfig?.public?.workflow ?? - (undefined as any); + runtimeConfig?.workflow ?? runtimeConfig?.public?.workflow ?? undefined; if (!workflow) return; From 5cc4824b45a54a48c3f32c52ac784a1ab71c37f5 Mon Sep 17 00:00:00 2001 From: Clay Levering Date: Tue, 16 Dec 2025 15:23:49 -0800 Subject: [PATCH 5/5] Update docs/content/docs/deploying/world/local-world.mdx Co-authored-by: Adrian --- docs/content/docs/deploying/world/local-world.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/deploying/world/local-world.mdx b/docs/content/docs/deploying/world/local-world.mdx index dedfb7360..8f0e2d473 100644 --- a/docs/content/docs/deploying/world/local-world.mdx +++ b/docs/content/docs/deploying/world/local-world.mdx @@ -116,7 +116,7 @@ export WORKFLOW_LOCAL_BASE_URL=https://local.example.com:3000 **Nuxt / Nitro runtime config (optional):** -If you're using Nuxt / Nitro and are running your app behind a reverse proxy, tunnel, custom hostname, or non-standard port, configure the origin via runtime config. Add this to your `nuxt.config.ts`: +If you're using Nuxt / Nitro and are running your app behind a reverse proxy, tunnel, custom hostname, or non-standard port, configure the origin via runtime config. Add this to your `nuxt.config.ts` or `nitro.config.ts`: ```typescript title="nuxt.config.ts" lineNumbers export default defineNuxtConfig({