Fix projectConfig.projectId containing project name instead of ID - #999

Merged
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config
Feb 18, 2026
Merged

Fix projectConfig.projectId containing project name instead of ID#999
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Feb 11, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes WORKFLOW_VERCEL_PROJECT env var to contain the real project ID instead of the project name/slug
  • Adds WORKFLOW_VERCEL_PROJECT_NAME for the project slug

@github-actions

github-actionsBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production534038572
✅ 💻 Local Development556068624
✅ 📦 Local Production556068624
✅ 🐘 Local Postgres556068624
✅ 🪟 Windows490352
❌ 🌍 Community Worlds111459165
✅ 📋 Other135021156
Total2497452752817

❌ Failed Tests

🌍 Community Worlds (45 failed)

turso (45 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • parallelSleepWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling retry behavior workflow completes despite transient 5xx on step_completed
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument
  • cancelRun - cancelling a running workflow
  • cancelRun via CLI - cancelling a running workflow
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro4804
✅ example4804
✅ express4804
✅ fastify4804
✅ hono4804
✅ nextjs-turbopack5101
✅ nextjs-webpack5101
✅ nitro4804
✅ nuxt4804
✅ sveltekit4804
✅ vite4804
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack4903
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev300
✅ mongodb4903
✅ redis-dev300
✅ redis4903
✅ turso-dev300
❌ turso4453
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable4507
✅ e2e-local-postgres-nest-stable4507
✅ e2e-local-prod-nest-stable4507

📋 View full workflow run

@changeset-bot

changeset-botBot commented Feb 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2a6cf4b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
@workflow/world-vercelPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/web-sharedPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNate marked this pull request as ready for review February 11, 2026 04:18
CopilotAI review requested due to automatic review settings February 11, 2026 04:18

@vercelvercelBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

Connection status UI displays opaque Vercel project ID (e.g., prj_xxx) instead of the human-readable project name after WORKFLOW_VERCEL_PROJECT was changed to store the real project ID.

Fix on Vercel

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes inconsistent handling of Vercel project identity by separating the project ID (used for API/auth/encryption contexts) from the project slug/name (used for dashboard URLs and display), and wires the new env var through CLI, core runtime, and the web server’s Vercel world creation path.

Changes:

  • Added WORKFLOW_VERCEL_PROJECT_NAME (project slug/name) alongside WORKFLOW_VERCEL_PROJECT (real prj_… id).
  • Updated CLI env inference to set WORKFLOW_VERCEL_PROJECT to the true project ID and populate the new project-name env var.
  • Plumbed projectName through core/runtime world creation and web server env allowlists / Vercel world instantiation.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
packages/world-vercel/src/utils.tsExtends Vercel world config typing to include both project ID and project slug/name.
packages/web/src/server/workflow-server-actions.tsAllows the new env var to reach the client and passes it into createVercelWorld().
packages/core/src/runtime/world.tsAdds WORKFLOW_VERCEL_PROJECT_NAME into the runtime’s Vercel world config.
packages/cli/src/lib/inspect/web.tsUses project slug/name (when available) for dashboard URL generation.
packages/cli/src/lib/inspect/env.tsAdds the new env var and updates Vercel env inference to distinguish ID vs name.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 203 to +207
'WORKFLOW_TARGET_WORLD',
'WORKFLOW_VERCEL_ENV',
'WORKFLOW_VERCEL_TEAM',
'WORKFLOW_VERCEL_PROJECT',
'WORKFLOW_VERCEL_PROJECT_NAME',

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says the web UI was updated to prefer the Vercel project name/slug when available, but the only consumer updated here appears to be the CLI dashboard URL logic. The web UI still appears to read/display WORKFLOW_VERCEL_PROJECT (now intended to be the prj_… id), so the UI may show IDs instead of friendly slugs unless the client-side components are updated to use WORKFLOW_VERCEL_PROJECT_NAME.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web UI path changed significantly during the React Router refactor. The web server actions now use createVercelWorld() which receives projectConfig with both projectId and projectName. The dashboard URL logic uses the name/slug.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web server actions use createVercelWorld() which receives both projectId and projectName via projectConfig. The dashboard URL uses the name/slug. No additional web UI changes needed.

Comment on lines +193 to +196
// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inferVercelEnvVars() only populates WORKFLOW_VERCEL_PROJECT_NAME (and normalizes WORKFLOW_VERCEL_PROJECT to a real prj_… id) when either WORKFLOW_VERCEL_PROJECT or WORKFLOW_VERCEL_TEAM is missing. If the CLI flag/env already sets WORKFLOW_VERCEL_PROJECT to a project slug/name (which the --project flag description currently implies), this block won’t run, and the world will continue sending the slug in the x-vercel-project-id header—reintroducing the exact bug this PR is fixing and potentially breaking auth/encryption context. Consider expanding the guard to also run when WORKFLOW_VERCEL_PROJECT_NAME is missing and/or when WORKFLOW_VERCEL_PROJECT doesn’t look like a Vercel project id (e.g. not prj_…), so the env vars are consistently normalized.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inference logic normalizes the env var to a real project ID when the linked project is available. If the user sets WORKFLOW_VERCEL_PROJECT to a slug, the inference step replaces it with the real ID from .vercel/project.json.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the guard now also runs when WORKFLOW_VERCEL_PROJECT does not start with prj_ or when WORKFLOW_VERCEL_PROJECT_NAME is missing, ensuring consistent normalization regardless of how the env vars were initially populated.

@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from a4be5e8 to 53d573eCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/encryptor-interface branch from 30fc9e5 to fc25b9cCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from 2746c5a to c6af179CompareFebruary 16, 2026 07:56

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but comment is changelog is off

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems off. The actual code doesn't change projectId at all. It seems more like:

Suggested change
Fix `projectConfig.projectId` to contain the real project ID instead of the project name
In UI, show project name instead in ID when available

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's not a UI change. In the world-vercel projectConfig, the projectId was previously being set to the project slug, not the ID.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the changeset description to: "Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)"

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is a clean and well-scoped fix. The separation of project ID vs project name/slug is the right approach. Two items to address:

  1. Connection status UI regression: packages/web/app/components/display-utils/connection-status.tsx:33 reads publicEnv.WORKFLOW_VERCEL_PROJECT to display the connection info string (e.g. team/project). Since WORKFLOW_VERCEL_PROJECT now contains the opaque prj_xxx ID, this will show IDs instead of friendly names. Should be updated to prefer WORKFLOW_VERCEL_PROJECT_NAME, same pattern as packages/cli/src/lib/inspect/web.ts:101-102:
constproject=publicEnv.WORKFLOW_VERCEL_PROJECT_NAME||publicEnv.WORKFLOW_VERCEL_PROJECT;

The Vercel bot flagged this as well.

  1. Changeset description is misleading (see inline comment).

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @VaguelySerious — the changeset description is misleading. The PR doesn't change what projectConfig.projectId contains (it was always the real project ID from .vercel/project.json). The actual fix is that WORKFLOW_VERCEL_PROJECT env var now correctly stores the real project ID instead of the project name/slug, and a new WORKFLOW_VERCEL_PROJECT_NAME env var is introduced for the slug.

Suggested:

Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — used your suggested wording.

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a broader pass across the codebase for project ID/name consistency. A few more things beyond my earlier review:

Naming inconsistency: WORKFLOW_VERCEL_PROJECT_SLUG vs WORKFLOW_VERCEL_PROJECT_NAME

CI already defines a third env var — WORKFLOW_VERCEL_PROJECT_SLUG — used in tests.yml:268, benchmarks.yml:397, and consumed by e2e tests (packages/core/e2e/e2e.test.ts:62) and benchmarks (packages/core/e2e/bench.bench.ts:156). This PR introduces WORKFLOW_VERCEL_PROJECT_NAME for the same concept. That's now two env vars for the project slug/name. Worth unifying on one name (probably WORKFLOW_VERCEL_PROJECT_NAME since it's the new standard) and updating CI + e2e tests to match, or at minimum documenting the relationship.

--project CLI flag can accept a slug

In packages/cli/src/lib/inspect/flags.ts:52-61, the --project flag maps directly to WORKFLOW_VERCEL_PROJECT. Its description says "the vercel project to authenticate against" — users could reasonably pass a slug here. In setup.ts:78, this value is written straight to WORKFLOW_VERCEL_PROJECTbeforeinferVercelEnvVars() runs. Since inferVercelEnvVars() only triggers when WORKFLOW_VERCEL_PROJECT is empty (line 188), a user-provided slug would persist as the "project ID" and get sent in the x-vercel-project-id header — reintroducing the original bug. This is the same concern Copilot raised. Consider either:

  • Normalizing in inferVercelEnvVars even when the env var is already set (e.g., if it doesn't start with prj_)
  • Or splitting the flag into --project-id and --project-name

projectName is carried but never consumed in world-vercel

The APIConfig.projectConfig.projectName field was added to the type in packages/world-vercel/src/utils.ts:40, but getHeaders() (line 173) and getHttpUrl() (line 155) never read it — only projectId and teamId are used for headers and proxy routing. This is fine since it's only for display, but a doc note clarifying it's not sent to the server would help future readers.

// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard on line 188 (!envVars.WORKFLOW_VERCEL_PROJECT || !envVars.WORKFLOW_VERCEL_TEAM) means inference is skipped entirely when both are already set. But WORKFLOW_VERCEL_PROJECT could contain a slug from the --project CLI flag (see flags.ts:58 and setup.ts:78), and WORKFLOW_VERCEL_PROJECT_NAME would remain empty.

Consider also running normalization when WORKFLOW_VERCEL_PROJECT is set but doesn't look like a real project ID (e.g., doesn't start with prj_), or when WORKFLOW_VERCEL_PROJECT_NAME is missing. This would make the env vars robust regardless of how they were initially populated.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Expanded the guard to also run inference when:

  • WORKFLOW_VERCEL_PROJECT does not start with prj_ (e.g., slug from --project flag)
  • WORKFLOW_VERCEL_PROJECT_NAME is missing

Also changed the team assignment to preserve an explicitly set team (envVars.WORKFLOW_VERCEL_TEAM || teamId) so only missing values get populated during normalization.

Comment threadpackages/core/src/runtime/world.ts Outdated
projectConfig: {
environment: process.env.WORKFLOW_VERCEL_ENV,
projectId: process.env.WORKFLOW_VERCEL_PROJECT,
projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could add a brief comment here (like in env.ts) clarifying the distinction:

projectId: process.env.WORKFLOW_VERCEL_PROJECT,// real ID (prj_xxx)projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,// slug (my-app)

Helps future readers understand the split without needing to trace back to the CLI.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added inline comments clarifying the distinction.

@github-actions

github-actionsBot commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.032s (+1.6%)1.005s (~)0.973s101.00x
💻 LocalNitro0.034s (+1.2%)1.005s (~)0.971s101.05x
🌐 RedisNext.js (Turbopack)0.038s1.005s0.967s101.18x
💻 LocalNext.js (Turbopack)0.043s1.004s0.961s101.33x
🌐 MongoDBNext.js (Turbopack)0.100s1.007s0.907s103.10x
🐘 PostgresNitro0.106s (-45.6% 🟢)1.010s (~)0.904s103.26x
🐘 PostgresExpress0.134s (-71.5% 🟢)1.010s (-0.5%)0.876s104.14x
🐘 PostgresNext.js (Turbopack)0.453s1.009s0.557s1013.97x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.513s (-13.6% 🟢)1.784s (-21.4% 🟢)1.271s101.00x
▲ VercelNitro0.684s (-1.0%)2.144s (+2.6%)1.460s101.33x
▲ VercelNext.js (Turbopack)0.979s (+34.7% 🔺)2.389s (+2.1%)1.410s101.91x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.089s2.006s0.918s101.00x
💻 LocalNext.js (Turbopack)1.095s2.005s0.910s101.01x
💻 LocalExpress1.105s (~)2.006s (~)0.900s101.02x
💻 LocalNitro1.112s (~)2.005s (~)0.893s101.02x
🌐 MongoDBNext.js (Turbopack)1.309s2.009s0.700s101.20x
🐘 PostgresNext.js (Turbopack)1.841s2.011s0.171s101.69x
🐘 PostgresExpress2.456s (+3.2%)3.014s (~)0.558s102.26x
🐘 PostgresNitro2.495s (+18.5% 🔺)3.013s (+3.4%)0.518s102.29x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.226s (-2.3%)3.401s (-4.2%)1.175s101.00x
▲ VercelNext.js (Turbopack)2.332s (+5.3% 🔺)3.767s (+7.6% 🔺)1.435s101.05x
▲ VercelNitro2.802s (+22.8% 🔺)4.038s (+28.6% 🔺)1.236s101.26x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)10.594s11.022s0.429s31.00x
💻 LocalNext.js (Turbopack)10.697s11.020s0.323s31.01x
💻 LocalExpress10.819s (~)11.023s (~)0.203s31.02x
💻 LocalNitro10.887s (~)11.024s (~)0.137s31.03x
🌐 MongoDBNext.js (Turbopack)12.341s13.022s0.680s31.16x
🐘 PostgresNext.js (Turbopack)15.273s16.043s0.771s21.44x
🐘 PostgresExpress20.327s (~)21.059s (~)0.732s21.92x
🐘 PostgresNitro20.388s (+32.0% 🔺)21.054s (+31.2% 🔺)0.666s21.92x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express17.270s (+0.9%)18.449s (+3.7%)1.179s21.00x
▲ VercelNext.js (Turbopack)17.501s (-2.8%)18.877s (-1.6%)1.376s21.01x
▲ VercelNitro18.538s (+5.0% 🔺)19.543s (+5.2% 🔺)1.005s21.07x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)26.563s27.051s0.488s31.00x
💻 LocalNext.js (Turbopack)27.133s28.048s0.915s31.02x
💻 LocalExpress27.473s (~)28.050s (~)0.577s31.03x
💻 LocalNitro27.607s (~)28.053s (~)0.446s31.04x
🌐 MongoDBNext.js (Turbopack)30.649s31.045s0.396s21.15x
🐘 PostgresNext.js (Turbopack)37.630s38.089s0.459s21.42x
🐘 PostgresNitro50.155s (+32.8% 🔺)50.622s (+32.9% 🔺)0.467s21.89x
🐘 PostgresExpress50.347s (~)51.133s (~)0.785s21.90x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express43.009s (-4.6%)45.845s (-2.6%)2.836s21.00x
▲ VercelNext.js (Turbopack)43.117s (-4.7%)44.092s (-4.4%)0.974s21.00x
▲ VercelNitro43.536s (+3.7%)45.021s (+3.7%)1.485s21.01x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)53.737s54.099s0.362s21.00x
💻 LocalNext.js (Turbopack)56.586s57.096s0.511s21.05x
💻 LocalExpress57.392s (~)58.101s (~)0.709s21.07x
💻 LocalNitro57.471s (~)58.104s (~)0.632s21.07x
🌐 MongoDBNext.js (Turbopack)61.136s61.582s0.446s21.14x
🐘 PostgresExpress75.430s (-24.7% 🟢)76.181s (-24.0% 🟢)0.750s21.40x
🐘 PostgresNext.js (Turbopack)75.573s76.172s0.599s21.41x
🐘 PostgresNitro77.254s (+2.4%)77.669s (+1.9%)0.415s21.44x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro86.156s (~)87.467s (~)1.311s21.00x
▲ VercelNext.js (Turbopack)87.287s (-1.0%)88.401s (-1.0%)1.113s21.01x
▲ VercelExpress92.167s (+6.0% 🔺)92.965s (+5.8% 🔺)0.798s11.07x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.209s2.006s0.797s151.00x
💻 LocalNext.js (Turbopack)1.377s2.004s0.627s151.14x
💻 LocalNitro1.406s (-2.3%)2.006s (~)0.599s151.16x
💻 LocalExpress1.412s (~)2.005s (~)0.593s151.17x
🐘 PostgresNext.js (Turbopack)1.929s2.226s0.297s141.59x
🐘 PostgresExpress2.002s (-11.5% 🟢)2.682s (-11.0% 🟢)0.681s121.66x
🌐 MongoDBNext.js (Turbopack)2.158s3.008s0.851s101.78x
🐘 PostgresNitro2.276s (+6.7% 🔺)3.015s (+10.0% 🔺)0.738s101.88x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.395s (-0.7%)3.370s (-3.1%)0.974s91.00x
▲ VercelNitro2.424s (-1.3%)3.783s (+7.5% 🔺)1.359s81.01x
▲ VercelNext.js (Turbopack)2.836s (+11.2% 🔺)3.768s (-1.6%)0.932s81.18x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.403s3.008s0.605s101.00x
💻 LocalNitro2.526s (-3.2%)3.008s (~)0.481s101.05x
💻 LocalNext.js (Turbopack)2.541s3.007s0.466s101.06x
💻 LocalExpress2.581s (-1.1%)3.006s (~)0.425s101.07x
🌐 MongoDBNext.js (Turbopack)4.693s5.178s0.485s61.95x
🐘 PostgresNitro6.872s (-35.7% 🟢)7.226s (-34.5% 🟢)0.354s52.86x
🐘 PostgresExpress10.043s (+7.1% 🔺)10.367s (+8.7% 🔺)0.323s34.18x
🐘 PostgresNext.js (Turbopack)10.800s11.367s0.567s34.49x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.567s (-12.0% 🟢)3.862s (-3.6%)1.295s81.00x
▲ VercelNext.js (Turbopack)2.701s (-21.9% 🟢)4.004s (-14.7% 🟢)1.304s81.05x
▲ VercelExpress3.794s (+21.5% 🔺)5.064s (+25.7% 🔺)1.271s61.48x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.929s4.135s0.206s81.00x
💻 LocalNitro7.258s (-3.1%)8.019s (~)0.762s41.85x
💻 LocalExpress7.423s (-1.3%)8.016s (~)0.593s41.89x
💻 LocalNext.js (Turbopack)7.486s7.769s0.282s41.91x
🌐 MongoDBNext.js (Turbopack)9.727s10.352s0.625s32.48x
🐘 PostgresExpress47.361s (-2.2%)48.107s (-2.1%)0.746s112.05x
🐘 PostgresNitro48.096s (-5.7% 🟢)48.117s (-5.9% 🟢)0.021s112.24x
🐘 PostgresNext.js (Turbopack)49.877s50.116s0.239s112.70x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.192s (~)4.148s (-10.5% 🟢)0.955s81.00x
▲ VercelExpress3.249s (-26.1% 🟢)4.185s (-32.5% 🟢)0.935s81.02x
▲ VercelNext.js (Turbopack)3.799s (-58.3% 🟢)5.156s (-48.1% 🟢)1.357s61.19x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.210s2.006s0.796s151.00x
💻 LocalExpress1.417s (-1.1%)2.006s (~)0.588s151.17x
💻 LocalNext.js (Turbopack)1.427s2.005s0.578s151.18x
💻 LocalNitro1.461s (+2.2%)2.006s (~)0.545s151.21x
🐘 PostgresNitro1.920s (-15.4% 🟢)2.078s (-20.0% 🟢)0.158s151.59x
🐘 PostgresNext.js (Turbopack)2.071s2.596s0.525s121.71x
🐘 PostgresExpress2.108s (-0.9%)2.475s (-15.3% 🟢)0.367s131.74x
🌐 MongoDBNext.js (Turbopack)2.156s3.008s0.853s101.78x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.127s (-74.5% 🟢)3.048s (-68.8% 🟢)0.920s101.00x
▲ VercelNitro2.218s (-69.7% 🟢)3.447s (-59.4% 🟢)1.229s91.04x
▲ VercelNext.js (Turbopack)2.425s (-8.7% 🟢)3.632s (-4.4%)1.207s91.14x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.360s3.008s0.648s101.00x
💻 LocalNext.js (Turbopack)2.599s3.008s0.409s101.10x
💻 LocalNitro2.670s (-1.1%)3.008s (~)0.338s101.13x
💻 LocalExpress2.689s (~)3.008s (~)0.319s101.14x
🌐 MongoDBNext.js (Turbopack)4.703s5.177s0.474s61.99x
🐘 PostgresNitro11.509s (+6.1% 🔺)12.370s (+5.7% 🔺)0.861s34.88x
🐘 PostgresNext.js (Turbopack)11.704s12.364s0.660s34.96x
🐘 PostgresExpress12.371s (+5.2% 🔺)12.702s (+2.7%)0.331s35.24x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.341s (-13.1% 🟢)3.165s (-22.6% 🟢)0.823s101.00x
▲ VercelNitro2.689s (~)4.346s (+19.2% 🔺)1.657s71.15x
▲ VercelNext.js (Turbopack)2.839s (-0.9%)3.983s (+4.1%)1.144s91.21x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.889s4.260s0.371s81.00x
💻 LocalNitro7.545s (-6.3% 🟢)8.020s (-5.9% 🟢)0.476s41.94x
💻 LocalNext.js (Turbopack)7.895s8.267s0.372s42.03x
💻 LocalExpress8.148s (+3.1%)9.024s (+2.9%)0.876s42.10x
🌐 MongoDBNext.js (Turbopack)9.732s10.351s0.619s32.50x
🐘 PostgresExpress49.140s (-3.9%)50.108s (-3.9%)0.968s112.64x
🐘 PostgresNitro53.097s (+1.9%)53.121s (~)0.024s113.65x
🐘 PostgresNext.js (Turbopack)56.257s57.116s0.859s114.47x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.627s (-24.6% 🟢)3.580s (-19.0% 🟢)0.953s91.00x
▲ VercelNext.js (Turbopack)3.118s (-31.2% 🟢)4.557s (-17.8% 🟢)1.439s71.19x
▲ VercelNitro4.048s (+34.3% 🔺)5.250s (+32.1% 🔺)1.202s61.54x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)0.110s1.000s0.001s1.007s0.896s101.00x
💻 LocalNext.js (Turbopack)0.140s1.001s0.011s1.016s0.876s101.27x
💻 LocalExpress0.173s (~)1.002s (~)0.011s (+7.5% 🔺)1.017s (~)0.844s101.57x
💻 LocalNitro0.188s (+0.6%)1.002s (~)0.010s (-15.8% 🟢)1.016s (~)0.828s101.71x
🌐 MongoDBNext.js (Turbopack)0.500s0.949s0.001s1.009s0.509s104.53x
🐘 PostgresExpress1.291s (-44.9% 🟢)1.831s (-32.2% 🟢)0.002s (+25.0% 🔺)2.013s (-33.2% 🟢)0.722s1011.70x
🐘 PostgresNext.js (Turbopack)1.391s1.655s0.001s2.013s0.622s1012.61x
🐘 PostgresNitro1.413s (+16.4% 🔺)1.694s (-7.1% 🟢)0.002s (+7.1% 🔺)2.012s (~)0.600s1012.81x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.016s (+3.0%)2.886s (+3.6%)0.164s (-66.7% 🟢)3.607s (-5.7% 🟢)1.591s101.00x
▲ VercelNitro2.051s (+7.7% 🔺)2.772s (-19.8% 🟢)0.545s (+310.7% 🔺)3.939s (-4.5%)1.888s101.02x
▲ VercelExpress2.080s (+5.0% 🔺)2.771s (~)0.660s (+212.5% 🔺)3.916s (+10.5% 🔺)1.836s101.03x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)7/12
🐘 PostgresNitro4/12
▲ VercelExpress8/12
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express💻 Local9/12
Next.js (Turbopack)🌐 Redis10/12
Nitro💻 Local10/12
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TooTallNate@pranaygp@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fix projectConfig.projectId containing project name instead of ID - #999

Merged
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config
Feb 18, 2026
Merged

Fix projectConfig.projectId containing project name instead of ID#999
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Feb 11, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes WORKFLOW_VERCEL_PROJECT env var to contain the real project ID instead of the project name/slug
  • Adds WORKFLOW_VERCEL_PROJECT_NAME for the project slug

@github-actions

github-actionsBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production534038572
✅ 💻 Local Development556068624
✅ 📦 Local Production556068624
✅ 🐘 Local Postgres556068624
✅ 🪟 Windows490352
❌ 🌍 Community Worlds111459165
✅ 📋 Other135021156
Total2497452752817

❌ Failed Tests

🌍 Community Worlds (45 failed)

turso (45 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • parallelSleepWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling retry behavior workflow completes despite transient 5xx on step_completed
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument
  • cancelRun - cancelling a running workflow
  • cancelRun via CLI - cancelling a running workflow
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro4804
✅ example4804
✅ express4804
✅ fastify4804
✅ hono4804
✅ nextjs-turbopack5101
✅ nextjs-webpack5101
✅ nitro4804
✅ nuxt4804
✅ sveltekit4804
✅ vite4804
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack4903
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev300
✅ mongodb4903
✅ redis-dev300
✅ redis4903
✅ turso-dev300
❌ turso4453
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable4507
✅ e2e-local-postgres-nest-stable4507
✅ e2e-local-prod-nest-stable4507

📋 View full workflow run

@changeset-bot

changeset-botBot commented Feb 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2a6cf4b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
@workflow/world-vercelPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/web-sharedPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNate marked this pull request as ready for review February 11, 2026 04:18
CopilotAI review requested due to automatic review settings February 11, 2026 04:18

@vercelvercelBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

Connection status UI displays opaque Vercel project ID (e.g., prj_xxx) instead of the human-readable project name after WORKFLOW_VERCEL_PROJECT was changed to store the real project ID.

Fix on Vercel

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes inconsistent handling of Vercel project identity by separating the project ID (used for API/auth/encryption contexts) from the project slug/name (used for dashboard URLs and display), and wires the new env var through CLI, core runtime, and the web server’s Vercel world creation path.

Changes:

  • Added WORKFLOW_VERCEL_PROJECT_NAME (project slug/name) alongside WORKFLOW_VERCEL_PROJECT (real prj_… id).
  • Updated CLI env inference to set WORKFLOW_VERCEL_PROJECT to the true project ID and populate the new project-name env var.
  • Plumbed projectName through core/runtime world creation and web server env allowlists / Vercel world instantiation.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
packages/world-vercel/src/utils.tsExtends Vercel world config typing to include both project ID and project slug/name.
packages/web/src/server/workflow-server-actions.tsAllows the new env var to reach the client and passes it into createVercelWorld().
packages/core/src/runtime/world.tsAdds WORKFLOW_VERCEL_PROJECT_NAME into the runtime’s Vercel world config.
packages/cli/src/lib/inspect/web.tsUses project slug/name (when available) for dashboard URL generation.
packages/cli/src/lib/inspect/env.tsAdds the new env var and updates Vercel env inference to distinguish ID vs name.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 203 to +207
'WORKFLOW_TARGET_WORLD',
'WORKFLOW_VERCEL_ENV',
'WORKFLOW_VERCEL_TEAM',
'WORKFLOW_VERCEL_PROJECT',
'WORKFLOW_VERCEL_PROJECT_NAME',

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says the web UI was updated to prefer the Vercel project name/slug when available, but the only consumer updated here appears to be the CLI dashboard URL logic. The web UI still appears to read/display WORKFLOW_VERCEL_PROJECT (now intended to be the prj_… id), so the UI may show IDs instead of friendly slugs unless the client-side components are updated to use WORKFLOW_VERCEL_PROJECT_NAME.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web UI path changed significantly during the React Router refactor. The web server actions now use createVercelWorld() which receives projectConfig with both projectId and projectName. The dashboard URL logic uses the name/slug.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web server actions use createVercelWorld() which receives both projectId and projectName via projectConfig. The dashboard URL uses the name/slug. No additional web UI changes needed.

Comment on lines +193 to +196
// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inferVercelEnvVars() only populates WORKFLOW_VERCEL_PROJECT_NAME (and normalizes WORKFLOW_VERCEL_PROJECT to a real prj_… id) when either WORKFLOW_VERCEL_PROJECT or WORKFLOW_VERCEL_TEAM is missing. If the CLI flag/env already sets WORKFLOW_VERCEL_PROJECT to a project slug/name (which the --project flag description currently implies), this block won’t run, and the world will continue sending the slug in the x-vercel-project-id header—reintroducing the exact bug this PR is fixing and potentially breaking auth/encryption context. Consider expanding the guard to also run when WORKFLOW_VERCEL_PROJECT_NAME is missing and/or when WORKFLOW_VERCEL_PROJECT doesn’t look like a Vercel project id (e.g. not prj_…), so the env vars are consistently normalized.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inference logic normalizes the env var to a real project ID when the linked project is available. If the user sets WORKFLOW_VERCEL_PROJECT to a slug, the inference step replaces it with the real ID from .vercel/project.json.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the guard now also runs when WORKFLOW_VERCEL_PROJECT does not start with prj_ or when WORKFLOW_VERCEL_PROJECT_NAME is missing, ensuring consistent normalization regardless of how the env vars were initially populated.

@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from a4be5e8 to 53d573eCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/encryptor-interface branch from 30fc9e5 to fc25b9cCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from 2746c5a to c6af179CompareFebruary 16, 2026 07:56

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but comment is changelog is off

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems off. The actual code doesn't change projectId at all. It seems more like:

Suggested change
Fix `projectConfig.projectId` to contain the real project ID instead of the project name
In UI, show project name instead in ID when available

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's not a UI change. In the world-vercel projectConfig, the projectId was previously being set to the project slug, not the ID.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the changeset description to: "Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)"

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is a clean and well-scoped fix. The separation of project ID vs project name/slug is the right approach. Two items to address:

  1. Connection status UI regression: packages/web/app/components/display-utils/connection-status.tsx:33 reads publicEnv.WORKFLOW_VERCEL_PROJECT to display the connection info string (e.g. team/project). Since WORKFLOW_VERCEL_PROJECT now contains the opaque prj_xxx ID, this will show IDs instead of friendly names. Should be updated to prefer WORKFLOW_VERCEL_PROJECT_NAME, same pattern as packages/cli/src/lib/inspect/web.ts:101-102:
constproject=publicEnv.WORKFLOW_VERCEL_PROJECT_NAME||publicEnv.WORKFLOW_VERCEL_PROJECT;

The Vercel bot flagged this as well.

  1. Changeset description is misleading (see inline comment).

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @VaguelySerious — the changeset description is misleading. The PR doesn't change what projectConfig.projectId contains (it was always the real project ID from .vercel/project.json). The actual fix is that WORKFLOW_VERCEL_PROJECT env var now correctly stores the real project ID instead of the project name/slug, and a new WORKFLOW_VERCEL_PROJECT_NAME env var is introduced for the slug.

Suggested:

Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — used your suggested wording.

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a broader pass across the codebase for project ID/name consistency. A few more things beyond my earlier review:

Naming inconsistency: WORKFLOW_VERCEL_PROJECT_SLUG vs WORKFLOW_VERCEL_PROJECT_NAME

CI already defines a third env var — WORKFLOW_VERCEL_PROJECT_SLUG — used in tests.yml:268, benchmarks.yml:397, and consumed by e2e tests (packages/core/e2e/e2e.test.ts:62) and benchmarks (packages/core/e2e/bench.bench.ts:156). This PR introduces WORKFLOW_VERCEL_PROJECT_NAME for the same concept. That's now two env vars for the project slug/name. Worth unifying on one name (probably WORKFLOW_VERCEL_PROJECT_NAME since it's the new standard) and updating CI + e2e tests to match, or at minimum documenting the relationship.

--project CLI flag can accept a slug

In packages/cli/src/lib/inspect/flags.ts:52-61, the --project flag maps directly to WORKFLOW_VERCEL_PROJECT. Its description says "the vercel project to authenticate against" — users could reasonably pass a slug here. In setup.ts:78, this value is written straight to WORKFLOW_VERCEL_PROJECTbeforeinferVercelEnvVars() runs. Since inferVercelEnvVars() only triggers when WORKFLOW_VERCEL_PROJECT is empty (line 188), a user-provided slug would persist as the "project ID" and get sent in the x-vercel-project-id header — reintroducing the original bug. This is the same concern Copilot raised. Consider either:

  • Normalizing in inferVercelEnvVars even when the env var is already set (e.g., if it doesn't start with prj_)
  • Or splitting the flag into --project-id and --project-name

projectName is carried but never consumed in world-vercel

The APIConfig.projectConfig.projectName field was added to the type in packages/world-vercel/src/utils.ts:40, but getHeaders() (line 173) and getHttpUrl() (line 155) never read it — only projectId and teamId are used for headers and proxy routing. This is fine since it's only for display, but a doc note clarifying it's not sent to the server would help future readers.

// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard on line 188 (!envVars.WORKFLOW_VERCEL_PROJECT || !envVars.WORKFLOW_VERCEL_TEAM) means inference is skipped entirely when both are already set. But WORKFLOW_VERCEL_PROJECT could contain a slug from the --project CLI flag (see flags.ts:58 and setup.ts:78), and WORKFLOW_VERCEL_PROJECT_NAME would remain empty.

Consider also running normalization when WORKFLOW_VERCEL_PROJECT is set but doesn't look like a real project ID (e.g., doesn't start with prj_), or when WORKFLOW_VERCEL_PROJECT_NAME is missing. This would make the env vars robust regardless of how they were initially populated.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Expanded the guard to also run inference when:

  • WORKFLOW_VERCEL_PROJECT does not start with prj_ (e.g., slug from --project flag)
  • WORKFLOW_VERCEL_PROJECT_NAME is missing

Also changed the team assignment to preserve an explicitly set team (envVars.WORKFLOW_VERCEL_TEAM || teamId) so only missing values get populated during normalization.

Comment threadpackages/core/src/runtime/world.ts Outdated
projectConfig: {
environment: process.env.WORKFLOW_VERCEL_ENV,
projectId: process.env.WORKFLOW_VERCEL_PROJECT,
projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could add a brief comment here (like in env.ts) clarifying the distinction:

projectId: process.env.WORKFLOW_VERCEL_PROJECT,// real ID (prj_xxx)projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,// slug (my-app)

Helps future readers understand the split without needing to trace back to the CLI.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added inline comments clarifying the distinction.

@github-actions

github-actionsBot commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.032s (+1.6%)1.005s (~)0.973s101.00x
💻 LocalNitro0.034s (+1.2%)1.005s (~)0.971s101.05x
🌐 RedisNext.js (Turbopack)0.038s1.005s0.967s101.18x
💻 LocalNext.js (Turbopack)0.043s1.004s0.961s101.33x
🌐 MongoDBNext.js (Turbopack)0.100s1.007s0.907s103.10x
🐘 PostgresNitro0.106s (-45.6% 🟢)1.010s (~)0.904s103.26x
🐘 PostgresExpress0.134s (-71.5% 🟢)1.010s (-0.5%)0.876s104.14x
🐘 PostgresNext.js (Turbopack)0.453s1.009s0.557s1013.97x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.513s (-13.6% 🟢)1.784s (-21.4% 🟢)1.271s101.00x
▲ VercelNitro0.684s (-1.0%)2.144s (+2.6%)1.460s101.33x
▲ VercelNext.js (Turbopack)0.979s (+34.7% 🔺)2.389s (+2.1%)1.410s101.91x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.089s2.006s0.918s101.00x
💻 LocalNext.js (Turbopack)1.095s2.005s0.910s101.01x
💻 LocalExpress1.105s (~)2.006s (~)0.900s101.02x
💻 LocalNitro1.112s (~)2.005s (~)0.893s101.02x
🌐 MongoDBNext.js (Turbopack)1.309s2.009s0.700s101.20x
🐘 PostgresNext.js (Turbopack)1.841s2.011s0.171s101.69x
🐘 PostgresExpress2.456s (+3.2%)3.014s (~)0.558s102.26x
🐘 PostgresNitro2.495s (+18.5% 🔺)3.013s (+3.4%)0.518s102.29x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.226s (-2.3%)3.401s (-4.2%)1.175s101.00x
▲ VercelNext.js (Turbopack)2.332s (+5.3% 🔺)3.767s (+7.6% 🔺)1.435s101.05x
▲ VercelNitro2.802s (+22.8% 🔺)4.038s (+28.6% 🔺)1.236s101.26x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)10.594s11.022s0.429s31.00x
💻 LocalNext.js (Turbopack)10.697s11.020s0.323s31.01x
💻 LocalExpress10.819s (~)11.023s (~)0.203s31.02x
💻 LocalNitro10.887s (~)11.024s (~)0.137s31.03x
🌐 MongoDBNext.js (Turbopack)12.341s13.022s0.680s31.16x
🐘 PostgresNext.js (Turbopack)15.273s16.043s0.771s21.44x
🐘 PostgresExpress20.327s (~)21.059s (~)0.732s21.92x
🐘 PostgresNitro20.388s (+32.0% 🔺)21.054s (+31.2% 🔺)0.666s21.92x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express17.270s (+0.9%)18.449s (+3.7%)1.179s21.00x
▲ VercelNext.js (Turbopack)17.501s (-2.8%)18.877s (-1.6%)1.376s21.01x
▲ VercelNitro18.538s (+5.0% 🔺)19.543s (+5.2% 🔺)1.005s21.07x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)26.563s27.051s0.488s31.00x
💻 LocalNext.js (Turbopack)27.133s28.048s0.915s31.02x
💻 LocalExpress27.473s (~)28.050s (~)0.577s31.03x
💻 LocalNitro27.607s (~)28.053s (~)0.446s31.04x
🌐 MongoDBNext.js (Turbopack)30.649s31.045s0.396s21.15x
🐘 PostgresNext.js (Turbopack)37.630s38.089s0.459s21.42x
🐘 PostgresNitro50.155s (+32.8% 🔺)50.622s (+32.9% 🔺)0.467s21.89x
🐘 PostgresExpress50.347s (~)51.133s (~)0.785s21.90x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express43.009s (-4.6%)45.845s (-2.6%)2.836s21.00x
▲ VercelNext.js (Turbopack)43.117s (-4.7%)44.092s (-4.4%)0.974s21.00x
▲ VercelNitro43.536s (+3.7%)45.021s (+3.7%)1.485s21.01x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)53.737s54.099s0.362s21.00x
💻 LocalNext.js (Turbopack)56.586s57.096s0.511s21.05x
💻 LocalExpress57.392s (~)58.101s (~)0.709s21.07x
💻 LocalNitro57.471s (~)58.104s (~)0.632s21.07x
🌐 MongoDBNext.js (Turbopack)61.136s61.582s0.446s21.14x
🐘 PostgresExpress75.430s (-24.7% 🟢)76.181s (-24.0% 🟢)0.750s21.40x
🐘 PostgresNext.js (Turbopack)75.573s76.172s0.599s21.41x
🐘 PostgresNitro77.254s (+2.4%)77.669s (+1.9%)0.415s21.44x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro86.156s (~)87.467s (~)1.311s21.00x
▲ VercelNext.js (Turbopack)87.287s (-1.0%)88.401s (-1.0%)1.113s21.01x
▲ VercelExpress92.167s (+6.0% 🔺)92.965s (+5.8% 🔺)0.798s11.07x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.209s2.006s0.797s151.00x
💻 LocalNext.js (Turbopack)1.377s2.004s0.627s151.14x
💻 LocalNitro1.406s (-2.3%)2.006s (~)0.599s151.16x
💻 LocalExpress1.412s (~)2.005s (~)0.593s151.17x
🐘 PostgresNext.js (Turbopack)1.929s2.226s0.297s141.59x
🐘 PostgresExpress2.002s (-11.5% 🟢)2.682s (-11.0% 🟢)0.681s121.66x
🌐 MongoDBNext.js (Turbopack)2.158s3.008s0.851s101.78x
🐘 PostgresNitro2.276s (+6.7% 🔺)3.015s (+10.0% 🔺)0.738s101.88x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.395s (-0.7%)3.370s (-3.1%)0.974s91.00x
▲ VercelNitro2.424s (-1.3%)3.783s (+7.5% 🔺)1.359s81.01x
▲ VercelNext.js (Turbopack)2.836s (+11.2% 🔺)3.768s (-1.6%)0.932s81.18x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.403s3.008s0.605s101.00x
💻 LocalNitro2.526s (-3.2%)3.008s (~)0.481s101.05x
💻 LocalNext.js (Turbopack)2.541s3.007s0.466s101.06x
💻 LocalExpress2.581s (-1.1%)3.006s (~)0.425s101.07x
🌐 MongoDBNext.js (Turbopack)4.693s5.178s0.485s61.95x
🐘 PostgresNitro6.872s (-35.7% 🟢)7.226s (-34.5% 🟢)0.354s52.86x
🐘 PostgresExpress10.043s (+7.1% 🔺)10.367s (+8.7% 🔺)0.323s34.18x
🐘 PostgresNext.js (Turbopack)10.800s11.367s0.567s34.49x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.567s (-12.0% 🟢)3.862s (-3.6%)1.295s81.00x
▲ VercelNext.js (Turbopack)2.701s (-21.9% 🟢)4.004s (-14.7% 🟢)1.304s81.05x
▲ VercelExpress3.794s (+21.5% 🔺)5.064s (+25.7% 🔺)1.271s61.48x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.929s4.135s0.206s81.00x
💻 LocalNitro7.258s (-3.1%)8.019s (~)0.762s41.85x
💻 LocalExpress7.423s (-1.3%)8.016s (~)0.593s41.89x
💻 LocalNext.js (Turbopack)7.486s7.769s0.282s41.91x
🌐 MongoDBNext.js (Turbopack)9.727s10.352s0.625s32.48x
🐘 PostgresExpress47.361s (-2.2%)48.107s (-2.1%)0.746s112.05x
🐘 PostgresNitro48.096s (-5.7% 🟢)48.117s (-5.9% 🟢)0.021s112.24x
🐘 PostgresNext.js (Turbopack)49.877s50.116s0.239s112.70x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.192s (~)4.148s (-10.5% 🟢)0.955s81.00x
▲ VercelExpress3.249s (-26.1% 🟢)4.185s (-32.5% 🟢)0.935s81.02x
▲ VercelNext.js (Turbopack)3.799s (-58.3% 🟢)5.156s (-48.1% 🟢)1.357s61.19x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.210s2.006s0.796s151.00x
💻 LocalExpress1.417s (-1.1%)2.006s (~)0.588s151.17x
💻 LocalNext.js (Turbopack)1.427s2.005s0.578s151.18x
💻 LocalNitro1.461s (+2.2%)2.006s (~)0.545s151.21x
🐘 PostgresNitro1.920s (-15.4% 🟢)2.078s (-20.0% 🟢)0.158s151.59x
🐘 PostgresNext.js (Turbopack)2.071s2.596s0.525s121.71x
🐘 PostgresExpress2.108s (-0.9%)2.475s (-15.3% 🟢)0.367s131.74x
🌐 MongoDBNext.js (Turbopack)2.156s3.008s0.853s101.78x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.127s (-74.5% 🟢)3.048s (-68.8% 🟢)0.920s101.00x
▲ VercelNitro2.218s (-69.7% 🟢)3.447s (-59.4% 🟢)1.229s91.04x
▲ VercelNext.js (Turbopack)2.425s (-8.7% 🟢)3.632s (-4.4%)1.207s91.14x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.360s3.008s0.648s101.00x
💻 LocalNext.js (Turbopack)2.599s3.008s0.409s101.10x
💻 LocalNitro2.670s (-1.1%)3.008s (~)0.338s101.13x
💻 LocalExpress2.689s (~)3.008s (~)0.319s101.14x
🌐 MongoDBNext.js (Turbopack)4.703s5.177s0.474s61.99x
🐘 PostgresNitro11.509s (+6.1% 🔺)12.370s (+5.7% 🔺)0.861s34.88x
🐘 PostgresNext.js (Turbopack)11.704s12.364s0.660s34.96x
🐘 PostgresExpress12.371s (+5.2% 🔺)12.702s (+2.7%)0.331s35.24x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.341s (-13.1% 🟢)3.165s (-22.6% 🟢)0.823s101.00x
▲ VercelNitro2.689s (~)4.346s (+19.2% 🔺)1.657s71.15x
▲ VercelNext.js (Turbopack)2.839s (-0.9%)3.983s (+4.1%)1.144s91.21x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.889s4.260s0.371s81.00x
💻 LocalNitro7.545s (-6.3% 🟢)8.020s (-5.9% 🟢)0.476s41.94x
💻 LocalNext.js (Turbopack)7.895s8.267s0.372s42.03x
💻 LocalExpress8.148s (+3.1%)9.024s (+2.9%)0.876s42.10x
🌐 MongoDBNext.js (Turbopack)9.732s10.351s0.619s32.50x
🐘 PostgresExpress49.140s (-3.9%)50.108s (-3.9%)0.968s112.64x
🐘 PostgresNitro53.097s (+1.9%)53.121s (~)0.024s113.65x
🐘 PostgresNext.js (Turbopack)56.257s57.116s0.859s114.47x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.627s (-24.6% 🟢)3.580s (-19.0% 🟢)0.953s91.00x
▲ VercelNext.js (Turbopack)3.118s (-31.2% 🟢)4.557s (-17.8% 🟢)1.439s71.19x
▲ VercelNitro4.048s (+34.3% 🔺)5.250s (+32.1% 🔺)1.202s61.54x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)0.110s1.000s0.001s1.007s0.896s101.00x
💻 LocalNext.js (Turbopack)0.140s1.001s0.011s1.016s0.876s101.27x
💻 LocalExpress0.173s (~)1.002s (~)0.011s (+7.5% 🔺)1.017s (~)0.844s101.57x
💻 LocalNitro0.188s (+0.6%)1.002s (~)0.010s (-15.8% 🟢)1.016s (~)0.828s101.71x
🌐 MongoDBNext.js (Turbopack)0.500s0.949s0.001s1.009s0.509s104.53x
🐘 PostgresExpress1.291s (-44.9% 🟢)1.831s (-32.2% 🟢)0.002s (+25.0% 🔺)2.013s (-33.2% 🟢)0.722s1011.70x
🐘 PostgresNext.js (Turbopack)1.391s1.655s0.001s2.013s0.622s1012.61x
🐘 PostgresNitro1.413s (+16.4% 🔺)1.694s (-7.1% 🟢)0.002s (+7.1% 🔺)2.012s (~)0.600s1012.81x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.016s (+3.0%)2.886s (+3.6%)0.164s (-66.7% 🟢)3.607s (-5.7% 🟢)1.591s101.00x
▲ VercelNitro2.051s (+7.7% 🔺)2.772s (-19.8% 🟢)0.545s (+310.7% 🔺)3.939s (-4.5%)1.888s101.02x
▲ VercelExpress2.080s (+5.0% 🔺)2.771s (~)0.660s (+212.5% 🔺)3.916s (+10.5% 🔺)1.836s101.03x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)7/12
🐘 PostgresNitro4/12
▲ VercelExpress8/12
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express💻 Local9/12
Next.js (Turbopack)🌐 Redis10/12
Nitro💻 Local10/12
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TooTallNate@pranaygp@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix projectConfig.projectId containing project name instead of ID - #999

Merged
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config
Feb 18, 2026
Merged

Fix projectConfig.projectId containing project name instead of ID#999
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Feb 11, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes WORKFLOW_VERCEL_PROJECT env var to contain the real project ID instead of the project name/slug
  • Adds WORKFLOW_VERCEL_PROJECT_NAME for the project slug

@github-actions

github-actionsBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production534038572
✅ 💻 Local Development556068624
✅ 📦 Local Production556068624
✅ 🐘 Local Postgres556068624
✅ 🪟 Windows490352
❌ 🌍 Community Worlds111459165
✅ 📋 Other135021156
Total2497452752817

❌ Failed Tests

🌍 Community Worlds (45 failed)

turso (45 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • parallelSleepWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling retry behavior workflow completes despite transient 5xx on step_completed
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument
  • cancelRun - cancelling a running workflow
  • cancelRun via CLI - cancelling a running workflow
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro4804
✅ example4804
✅ express4804
✅ fastify4804
✅ hono4804
✅ nextjs-turbopack5101
✅ nextjs-webpack5101
✅ nitro4804
✅ nuxt4804
✅ sveltekit4804
✅ vite4804
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack4903
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev300
✅ mongodb4903
✅ redis-dev300
✅ redis4903
✅ turso-dev300
❌ turso4453
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable4507
✅ e2e-local-postgres-nest-stable4507
✅ e2e-local-prod-nest-stable4507

📋 View full workflow run

@changeset-bot

changeset-botBot commented Feb 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2a6cf4b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
@workflow/world-vercelPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/web-sharedPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNate marked this pull request as ready for review February 11, 2026 04:18
CopilotAI review requested due to automatic review settings February 11, 2026 04:18

@vercelvercelBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

Connection status UI displays opaque Vercel project ID (e.g., prj_xxx) instead of the human-readable project name after WORKFLOW_VERCEL_PROJECT was changed to store the real project ID.

Fix on Vercel

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes inconsistent handling of Vercel project identity by separating the project ID (used for API/auth/encryption contexts) from the project slug/name (used for dashboard URLs and display), and wires the new env var through CLI, core runtime, and the web server’s Vercel world creation path.

Changes:

  • Added WORKFLOW_VERCEL_PROJECT_NAME (project slug/name) alongside WORKFLOW_VERCEL_PROJECT (real prj_… id).
  • Updated CLI env inference to set WORKFLOW_VERCEL_PROJECT to the true project ID and populate the new project-name env var.
  • Plumbed projectName through core/runtime world creation and web server env allowlists / Vercel world instantiation.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
packages/world-vercel/src/utils.tsExtends Vercel world config typing to include both project ID and project slug/name.
packages/web/src/server/workflow-server-actions.tsAllows the new env var to reach the client and passes it into createVercelWorld().
packages/core/src/runtime/world.tsAdds WORKFLOW_VERCEL_PROJECT_NAME into the runtime’s Vercel world config.
packages/cli/src/lib/inspect/web.tsUses project slug/name (when available) for dashboard URL generation.
packages/cli/src/lib/inspect/env.tsAdds the new env var and updates Vercel env inference to distinguish ID vs name.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 203 to +207
'WORKFLOW_TARGET_WORLD',
'WORKFLOW_VERCEL_ENV',
'WORKFLOW_VERCEL_TEAM',
'WORKFLOW_VERCEL_PROJECT',
'WORKFLOW_VERCEL_PROJECT_NAME',

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says the web UI was updated to prefer the Vercel project name/slug when available, but the only consumer updated here appears to be the CLI dashboard URL logic. The web UI still appears to read/display WORKFLOW_VERCEL_PROJECT (now intended to be the prj_… id), so the UI may show IDs instead of friendly slugs unless the client-side components are updated to use WORKFLOW_VERCEL_PROJECT_NAME.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web UI path changed significantly during the React Router refactor. The web server actions now use createVercelWorld() which receives projectConfig with both projectId and projectName. The dashboard URL logic uses the name/slug.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web server actions use createVercelWorld() which receives both projectId and projectName via projectConfig. The dashboard URL uses the name/slug. No additional web UI changes needed.

Comment on lines +193 to +196
// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inferVercelEnvVars() only populates WORKFLOW_VERCEL_PROJECT_NAME (and normalizes WORKFLOW_VERCEL_PROJECT to a real prj_… id) when either WORKFLOW_VERCEL_PROJECT or WORKFLOW_VERCEL_TEAM is missing. If the CLI flag/env already sets WORKFLOW_VERCEL_PROJECT to a project slug/name (which the --project flag description currently implies), this block won’t run, and the world will continue sending the slug in the x-vercel-project-id header—reintroducing the exact bug this PR is fixing and potentially breaking auth/encryption context. Consider expanding the guard to also run when WORKFLOW_VERCEL_PROJECT_NAME is missing and/or when WORKFLOW_VERCEL_PROJECT doesn’t look like a Vercel project id (e.g. not prj_…), so the env vars are consistently normalized.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inference logic normalizes the env var to a real project ID when the linked project is available. If the user sets WORKFLOW_VERCEL_PROJECT to a slug, the inference step replaces it with the real ID from .vercel/project.json.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the guard now also runs when WORKFLOW_VERCEL_PROJECT does not start with prj_ or when WORKFLOW_VERCEL_PROJECT_NAME is missing, ensuring consistent normalization regardless of how the env vars were initially populated.

@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from a4be5e8 to 53d573eCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/encryptor-interface branch from 30fc9e5 to fc25b9cCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from 2746c5a to c6af179CompareFebruary 16, 2026 07:56

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but comment is changelog is off

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems off. The actual code doesn't change projectId at all. It seems more like:

Suggested change
Fix `projectConfig.projectId` to contain the real project ID instead of the project name
In UI, show project name instead in ID when available

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's not a UI change. In the world-vercel projectConfig, the projectId was previously being set to the project slug, not the ID.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the changeset description to: "Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)"

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is a clean and well-scoped fix. The separation of project ID vs project name/slug is the right approach. Two items to address:

  1. Connection status UI regression: packages/web/app/components/display-utils/connection-status.tsx:33 reads publicEnv.WORKFLOW_VERCEL_PROJECT to display the connection info string (e.g. team/project). Since WORKFLOW_VERCEL_PROJECT now contains the opaque prj_xxx ID, this will show IDs instead of friendly names. Should be updated to prefer WORKFLOW_VERCEL_PROJECT_NAME, same pattern as packages/cli/src/lib/inspect/web.ts:101-102:
constproject=publicEnv.WORKFLOW_VERCEL_PROJECT_NAME||publicEnv.WORKFLOW_VERCEL_PROJECT;

The Vercel bot flagged this as well.

  1. Changeset description is misleading (see inline comment).

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @VaguelySerious — the changeset description is misleading. The PR doesn't change what projectConfig.projectId contains (it was always the real project ID from .vercel/project.json). The actual fix is that WORKFLOW_VERCEL_PROJECT env var now correctly stores the real project ID instead of the project name/slug, and a new WORKFLOW_VERCEL_PROJECT_NAME env var is introduced for the slug.

Suggested:

Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — used your suggested wording.

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a broader pass across the codebase for project ID/name consistency. A few more things beyond my earlier review:

Naming inconsistency: WORKFLOW_VERCEL_PROJECT_SLUG vs WORKFLOW_VERCEL_PROJECT_NAME

CI already defines a third env var — WORKFLOW_VERCEL_PROJECT_SLUG — used in tests.yml:268, benchmarks.yml:397, and consumed by e2e tests (packages/core/e2e/e2e.test.ts:62) and benchmarks (packages/core/e2e/bench.bench.ts:156). This PR introduces WORKFLOW_VERCEL_PROJECT_NAME for the same concept. That's now two env vars for the project slug/name. Worth unifying on one name (probably WORKFLOW_VERCEL_PROJECT_NAME since it's the new standard) and updating CI + e2e tests to match, or at minimum documenting the relationship.

--project CLI flag can accept a slug

In packages/cli/src/lib/inspect/flags.ts:52-61, the --project flag maps directly to WORKFLOW_VERCEL_PROJECT. Its description says "the vercel project to authenticate against" — users could reasonably pass a slug here. In setup.ts:78, this value is written straight to WORKFLOW_VERCEL_PROJECTbeforeinferVercelEnvVars() runs. Since inferVercelEnvVars() only triggers when WORKFLOW_VERCEL_PROJECT is empty (line 188), a user-provided slug would persist as the "project ID" and get sent in the x-vercel-project-id header — reintroducing the original bug. This is the same concern Copilot raised. Consider either:

  • Normalizing in inferVercelEnvVars even when the env var is already set (e.g., if it doesn't start with prj_)
  • Or splitting the flag into --project-id and --project-name

projectName is carried but never consumed in world-vercel

The APIConfig.projectConfig.projectName field was added to the type in packages/world-vercel/src/utils.ts:40, but getHeaders() (line 173) and getHttpUrl() (line 155) never read it — only projectId and teamId are used for headers and proxy routing. This is fine since it's only for display, but a doc note clarifying it's not sent to the server would help future readers.

// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard on line 188 (!envVars.WORKFLOW_VERCEL_PROJECT || !envVars.WORKFLOW_VERCEL_TEAM) means inference is skipped entirely when both are already set. But WORKFLOW_VERCEL_PROJECT could contain a slug from the --project CLI flag (see flags.ts:58 and setup.ts:78), and WORKFLOW_VERCEL_PROJECT_NAME would remain empty.

Consider also running normalization when WORKFLOW_VERCEL_PROJECT is set but doesn't look like a real project ID (e.g., doesn't start with prj_), or when WORKFLOW_VERCEL_PROJECT_NAME is missing. This would make the env vars robust regardless of how they were initially populated.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Expanded the guard to also run inference when:

  • WORKFLOW_VERCEL_PROJECT does not start with prj_ (e.g., slug from --project flag)
  • WORKFLOW_VERCEL_PROJECT_NAME is missing

Also changed the team assignment to preserve an explicitly set team (envVars.WORKFLOW_VERCEL_TEAM || teamId) so only missing values get populated during normalization.

Comment threadpackages/core/src/runtime/world.ts Outdated
projectConfig: {
environment: process.env.WORKFLOW_VERCEL_ENV,
projectId: process.env.WORKFLOW_VERCEL_PROJECT,
projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could add a brief comment here (like in env.ts) clarifying the distinction:

projectId: process.env.WORKFLOW_VERCEL_PROJECT,// real ID (prj_xxx)projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,// slug (my-app)

Helps future readers understand the split without needing to trace back to the CLI.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added inline comments clarifying the distinction.

@github-actions

github-actionsBot commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.032s (+1.6%)1.005s (~)0.973s101.00x
💻 LocalNitro0.034s (+1.2%)1.005s (~)0.971s101.05x
🌐 RedisNext.js (Turbopack)0.038s1.005s0.967s101.18x
💻 LocalNext.js (Turbopack)0.043s1.004s0.961s101.33x
🌐 MongoDBNext.js (Turbopack)0.100s1.007s0.907s103.10x
🐘 PostgresNitro0.106s (-45.6% 🟢)1.010s (~)0.904s103.26x
🐘 PostgresExpress0.134s (-71.5% 🟢)1.010s (-0.5%)0.876s104.14x
🐘 PostgresNext.js (Turbopack)0.453s1.009s0.557s1013.97x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.513s (-13.6% 🟢)1.784s (-21.4% 🟢)1.271s101.00x
▲ VercelNitro0.684s (-1.0%)2.144s (+2.6%)1.460s101.33x
▲ VercelNext.js (Turbopack)0.979s (+34.7% 🔺)2.389s (+2.1%)1.410s101.91x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.089s2.006s0.918s101.00x
💻 LocalNext.js (Turbopack)1.095s2.005s0.910s101.01x
💻 LocalExpress1.105s (~)2.006s (~)0.900s101.02x
💻 LocalNitro1.112s (~)2.005s (~)0.893s101.02x
🌐 MongoDBNext.js (Turbopack)1.309s2.009s0.700s101.20x
🐘 PostgresNext.js (Turbopack)1.841s2.011s0.171s101.69x
🐘 PostgresExpress2.456s (+3.2%)3.014s (~)0.558s102.26x
🐘 PostgresNitro2.495s (+18.5% 🔺)3.013s (+3.4%)0.518s102.29x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.226s (-2.3%)3.401s (-4.2%)1.175s101.00x
▲ VercelNext.js (Turbopack)2.332s (+5.3% 🔺)3.767s (+7.6% 🔺)1.435s101.05x
▲ VercelNitro2.802s (+22.8% 🔺)4.038s (+28.6% 🔺)1.236s101.26x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)10.594s11.022s0.429s31.00x
💻 LocalNext.js (Turbopack)10.697s11.020s0.323s31.01x
💻 LocalExpress10.819s (~)11.023s (~)0.203s31.02x
💻 LocalNitro10.887s (~)11.024s (~)0.137s31.03x
🌐 MongoDBNext.js (Turbopack)12.341s13.022s0.680s31.16x
🐘 PostgresNext.js (Turbopack)15.273s16.043s0.771s21.44x
🐘 PostgresExpress20.327s (~)21.059s (~)0.732s21.92x
🐘 PostgresNitro20.388s (+32.0% 🔺)21.054s (+31.2% 🔺)0.666s21.92x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express17.270s (+0.9%)18.449s (+3.7%)1.179s21.00x
▲ VercelNext.js (Turbopack)17.501s (-2.8%)18.877s (-1.6%)1.376s21.01x
▲ VercelNitro18.538s (+5.0% 🔺)19.543s (+5.2% 🔺)1.005s21.07x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)26.563s27.051s0.488s31.00x
💻 LocalNext.js (Turbopack)27.133s28.048s0.915s31.02x
💻 LocalExpress27.473s (~)28.050s (~)0.577s31.03x
💻 LocalNitro27.607s (~)28.053s (~)0.446s31.04x
🌐 MongoDBNext.js (Turbopack)30.649s31.045s0.396s21.15x
🐘 PostgresNext.js (Turbopack)37.630s38.089s0.459s21.42x
🐘 PostgresNitro50.155s (+32.8% 🔺)50.622s (+32.9% 🔺)0.467s21.89x
🐘 PostgresExpress50.347s (~)51.133s (~)0.785s21.90x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express43.009s (-4.6%)45.845s (-2.6%)2.836s21.00x
▲ VercelNext.js (Turbopack)43.117s (-4.7%)44.092s (-4.4%)0.974s21.00x
▲ VercelNitro43.536s (+3.7%)45.021s (+3.7%)1.485s21.01x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)53.737s54.099s0.362s21.00x
💻 LocalNext.js (Turbopack)56.586s57.096s0.511s21.05x
💻 LocalExpress57.392s (~)58.101s (~)0.709s21.07x
💻 LocalNitro57.471s (~)58.104s (~)0.632s21.07x
🌐 MongoDBNext.js (Turbopack)61.136s61.582s0.446s21.14x
🐘 PostgresExpress75.430s (-24.7% 🟢)76.181s (-24.0% 🟢)0.750s21.40x
🐘 PostgresNext.js (Turbopack)75.573s76.172s0.599s21.41x
🐘 PostgresNitro77.254s (+2.4%)77.669s (+1.9%)0.415s21.44x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro86.156s (~)87.467s (~)1.311s21.00x
▲ VercelNext.js (Turbopack)87.287s (-1.0%)88.401s (-1.0%)1.113s21.01x
▲ VercelExpress92.167s (+6.0% 🔺)92.965s (+5.8% 🔺)0.798s11.07x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.209s2.006s0.797s151.00x
💻 LocalNext.js (Turbopack)1.377s2.004s0.627s151.14x
💻 LocalNitro1.406s (-2.3%)2.006s (~)0.599s151.16x
💻 LocalExpress1.412s (~)2.005s (~)0.593s151.17x
🐘 PostgresNext.js (Turbopack)1.929s2.226s0.297s141.59x
🐘 PostgresExpress2.002s (-11.5% 🟢)2.682s (-11.0% 🟢)0.681s121.66x
🌐 MongoDBNext.js (Turbopack)2.158s3.008s0.851s101.78x
🐘 PostgresNitro2.276s (+6.7% 🔺)3.015s (+10.0% 🔺)0.738s101.88x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.395s (-0.7%)3.370s (-3.1%)0.974s91.00x
▲ VercelNitro2.424s (-1.3%)3.783s (+7.5% 🔺)1.359s81.01x
▲ VercelNext.js (Turbopack)2.836s (+11.2% 🔺)3.768s (-1.6%)0.932s81.18x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.403s3.008s0.605s101.00x
💻 LocalNitro2.526s (-3.2%)3.008s (~)0.481s101.05x
💻 LocalNext.js (Turbopack)2.541s3.007s0.466s101.06x
💻 LocalExpress2.581s (-1.1%)3.006s (~)0.425s101.07x
🌐 MongoDBNext.js (Turbopack)4.693s5.178s0.485s61.95x
🐘 PostgresNitro6.872s (-35.7% 🟢)7.226s (-34.5% 🟢)0.354s52.86x
🐘 PostgresExpress10.043s (+7.1% 🔺)10.367s (+8.7% 🔺)0.323s34.18x
🐘 PostgresNext.js (Turbopack)10.800s11.367s0.567s34.49x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.567s (-12.0% 🟢)3.862s (-3.6%)1.295s81.00x
▲ VercelNext.js (Turbopack)2.701s (-21.9% 🟢)4.004s (-14.7% 🟢)1.304s81.05x
▲ VercelExpress3.794s (+21.5% 🔺)5.064s (+25.7% 🔺)1.271s61.48x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.929s4.135s0.206s81.00x
💻 LocalNitro7.258s (-3.1%)8.019s (~)0.762s41.85x
💻 LocalExpress7.423s (-1.3%)8.016s (~)0.593s41.89x
💻 LocalNext.js (Turbopack)7.486s7.769s0.282s41.91x
🌐 MongoDBNext.js (Turbopack)9.727s10.352s0.625s32.48x
🐘 PostgresExpress47.361s (-2.2%)48.107s (-2.1%)0.746s112.05x
🐘 PostgresNitro48.096s (-5.7% 🟢)48.117s (-5.9% 🟢)0.021s112.24x
🐘 PostgresNext.js (Turbopack)49.877s50.116s0.239s112.70x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.192s (~)4.148s (-10.5% 🟢)0.955s81.00x
▲ VercelExpress3.249s (-26.1% 🟢)4.185s (-32.5% 🟢)0.935s81.02x
▲ VercelNext.js (Turbopack)3.799s (-58.3% 🟢)5.156s (-48.1% 🟢)1.357s61.19x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.210s2.006s0.796s151.00x
💻 LocalExpress1.417s (-1.1%)2.006s (~)0.588s151.17x
💻 LocalNext.js (Turbopack)1.427s2.005s0.578s151.18x
💻 LocalNitro1.461s (+2.2%)2.006s (~)0.545s151.21x
🐘 PostgresNitro1.920s (-15.4% 🟢)2.078s (-20.0% 🟢)0.158s151.59x
🐘 PostgresNext.js (Turbopack)2.071s2.596s0.525s121.71x
🐘 PostgresExpress2.108s (-0.9%)2.475s (-15.3% 🟢)0.367s131.74x
🌐 MongoDBNext.js (Turbopack)2.156s3.008s0.853s101.78x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.127s (-74.5% 🟢)3.048s (-68.8% 🟢)0.920s101.00x
▲ VercelNitro2.218s (-69.7% 🟢)3.447s (-59.4% 🟢)1.229s91.04x
▲ VercelNext.js (Turbopack)2.425s (-8.7% 🟢)3.632s (-4.4%)1.207s91.14x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.360s3.008s0.648s101.00x
💻 LocalNext.js (Turbopack)2.599s3.008s0.409s101.10x
💻 LocalNitro2.670s (-1.1%)3.008s (~)0.338s101.13x
💻 LocalExpress2.689s (~)3.008s (~)0.319s101.14x
🌐 MongoDBNext.js (Turbopack)4.703s5.177s0.474s61.99x
🐘 PostgresNitro11.509s (+6.1% 🔺)12.370s (+5.7% 🔺)0.861s34.88x
🐘 PostgresNext.js (Turbopack)11.704s12.364s0.660s34.96x
🐘 PostgresExpress12.371s (+5.2% 🔺)12.702s (+2.7%)0.331s35.24x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.341s (-13.1% 🟢)3.165s (-22.6% 🟢)0.823s101.00x
▲ VercelNitro2.689s (~)4.346s (+19.2% 🔺)1.657s71.15x
▲ VercelNext.js (Turbopack)2.839s (-0.9%)3.983s (+4.1%)1.144s91.21x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.889s4.260s0.371s81.00x
💻 LocalNitro7.545s (-6.3% 🟢)8.020s (-5.9% 🟢)0.476s41.94x
💻 LocalNext.js (Turbopack)7.895s8.267s0.372s42.03x
💻 LocalExpress8.148s (+3.1%)9.024s (+2.9%)0.876s42.10x
🌐 MongoDBNext.js (Turbopack)9.732s10.351s0.619s32.50x
🐘 PostgresExpress49.140s (-3.9%)50.108s (-3.9%)0.968s112.64x
🐘 PostgresNitro53.097s (+1.9%)53.121s (~)0.024s113.65x
🐘 PostgresNext.js (Turbopack)56.257s57.116s0.859s114.47x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.627s (-24.6% 🟢)3.580s (-19.0% 🟢)0.953s91.00x
▲ VercelNext.js (Turbopack)3.118s (-31.2% 🟢)4.557s (-17.8% 🟢)1.439s71.19x
▲ VercelNitro4.048s (+34.3% 🔺)5.250s (+32.1% 🔺)1.202s61.54x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)0.110s1.000s0.001s1.007s0.896s101.00x
💻 LocalNext.js (Turbopack)0.140s1.001s0.011s1.016s0.876s101.27x
💻 LocalExpress0.173s (~)1.002s (~)0.011s (+7.5% 🔺)1.017s (~)0.844s101.57x
💻 LocalNitro0.188s (+0.6%)1.002s (~)0.010s (-15.8% 🟢)1.016s (~)0.828s101.71x
🌐 MongoDBNext.js (Turbopack)0.500s0.949s0.001s1.009s0.509s104.53x
🐘 PostgresExpress1.291s (-44.9% 🟢)1.831s (-32.2% 🟢)0.002s (+25.0% 🔺)2.013s (-33.2% 🟢)0.722s1011.70x
🐘 PostgresNext.js (Turbopack)1.391s1.655s0.001s2.013s0.622s1012.61x
🐘 PostgresNitro1.413s (+16.4% 🔺)1.694s (-7.1% 🟢)0.002s (+7.1% 🔺)2.012s (~)0.600s1012.81x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.016s (+3.0%)2.886s (+3.6%)0.164s (-66.7% 🟢)3.607s (-5.7% 🟢)1.591s101.00x
▲ VercelNitro2.051s (+7.7% 🔺)2.772s (-19.8% 🟢)0.545s (+310.7% 🔺)3.939s (-4.5%)1.888s101.02x
▲ VercelExpress2.080s (+5.0% 🔺)2.771s (~)0.660s (+212.5% 🔺)3.916s (+10.5% 🔺)1.836s101.03x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)7/12
🐘 PostgresNitro4/12
▲ VercelExpress8/12
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express💻 Local9/12
Next.js (Turbopack)🌐 Redis10/12
Nitro💻 Local10/12
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TooTallNate@pranaygp@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix projectConfig.projectId containing project name instead of ID - #999

Merged
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config
Feb 18, 2026
Merged

Fix projectConfig.projectId containing project name instead of ID#999
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Feb 11, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes WORKFLOW_VERCEL_PROJECT env var to contain the real project ID instead of the project name/slug
  • Adds WORKFLOW_VERCEL_PROJECT_NAME for the project slug

@github-actions

github-actionsBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production534038572
✅ 💻 Local Development556068624
✅ 📦 Local Production556068624
✅ 🐘 Local Postgres556068624
✅ 🪟 Windows490352
❌ 🌍 Community Worlds111459165
✅ 📋 Other135021156
Total2497452752817

❌ Failed Tests

🌍 Community Worlds (45 failed)

turso (45 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • parallelSleepWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling retry behavior workflow completes despite transient 5xx on step_completed
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument
  • cancelRun - cancelling a running workflow
  • cancelRun via CLI - cancelling a running workflow
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro4804
✅ example4804
✅ express4804
✅ fastify4804
✅ hono4804
✅ nextjs-turbopack5101
✅ nextjs-webpack5101
✅ nitro4804
✅ nuxt4804
✅ sveltekit4804
✅ vite4804
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack4903
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev300
✅ mongodb4903
✅ redis-dev300
✅ redis4903
✅ turso-dev300
❌ turso4453
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable4507
✅ e2e-local-postgres-nest-stable4507
✅ e2e-local-prod-nest-stable4507

📋 View full workflow run

@changeset-bot

changeset-botBot commented Feb 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2a6cf4b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
@workflow/world-vercelPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/web-sharedPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNate marked this pull request as ready for review February 11, 2026 04:18
CopilotAI review requested due to automatic review settings February 11, 2026 04:18

@vercelvercelBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

Connection status UI displays opaque Vercel project ID (e.g., prj_xxx) instead of the human-readable project name after WORKFLOW_VERCEL_PROJECT was changed to store the real project ID.

Fix on Vercel

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes inconsistent handling of Vercel project identity by separating the project ID (used for API/auth/encryption contexts) from the project slug/name (used for dashboard URLs and display), and wires the new env var through CLI, core runtime, and the web server’s Vercel world creation path.

Changes:

  • Added WORKFLOW_VERCEL_PROJECT_NAME (project slug/name) alongside WORKFLOW_VERCEL_PROJECT (real prj_… id).
  • Updated CLI env inference to set WORKFLOW_VERCEL_PROJECT to the true project ID and populate the new project-name env var.
  • Plumbed projectName through core/runtime world creation and web server env allowlists / Vercel world instantiation.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
packages/world-vercel/src/utils.tsExtends Vercel world config typing to include both project ID and project slug/name.
packages/web/src/server/workflow-server-actions.tsAllows the new env var to reach the client and passes it into createVercelWorld().
packages/core/src/runtime/world.tsAdds WORKFLOW_VERCEL_PROJECT_NAME into the runtime’s Vercel world config.
packages/cli/src/lib/inspect/web.tsUses project slug/name (when available) for dashboard URL generation.
packages/cli/src/lib/inspect/env.tsAdds the new env var and updates Vercel env inference to distinguish ID vs name.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 203 to +207
'WORKFLOW_TARGET_WORLD',
'WORKFLOW_VERCEL_ENV',
'WORKFLOW_VERCEL_TEAM',
'WORKFLOW_VERCEL_PROJECT',
'WORKFLOW_VERCEL_PROJECT_NAME',

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says the web UI was updated to prefer the Vercel project name/slug when available, but the only consumer updated here appears to be the CLI dashboard URL logic. The web UI still appears to read/display WORKFLOW_VERCEL_PROJECT (now intended to be the prj_… id), so the UI may show IDs instead of friendly slugs unless the client-side components are updated to use WORKFLOW_VERCEL_PROJECT_NAME.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web UI path changed significantly during the React Router refactor. The web server actions now use createVercelWorld() which receives projectConfig with both projectId and projectName. The dashboard URL logic uses the name/slug.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web server actions use createVercelWorld() which receives both projectId and projectName via projectConfig. The dashboard URL uses the name/slug. No additional web UI changes needed.

Comment on lines +193 to +196
// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inferVercelEnvVars() only populates WORKFLOW_VERCEL_PROJECT_NAME (and normalizes WORKFLOW_VERCEL_PROJECT to a real prj_… id) when either WORKFLOW_VERCEL_PROJECT or WORKFLOW_VERCEL_TEAM is missing. If the CLI flag/env already sets WORKFLOW_VERCEL_PROJECT to a project slug/name (which the --project flag description currently implies), this block won’t run, and the world will continue sending the slug in the x-vercel-project-id header—reintroducing the exact bug this PR is fixing and potentially breaking auth/encryption context. Consider expanding the guard to also run when WORKFLOW_VERCEL_PROJECT_NAME is missing and/or when WORKFLOW_VERCEL_PROJECT doesn’t look like a Vercel project id (e.g. not prj_…), so the env vars are consistently normalized.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inference logic normalizes the env var to a real project ID when the linked project is available. If the user sets WORKFLOW_VERCEL_PROJECT to a slug, the inference step replaces it with the real ID from .vercel/project.json.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the guard now also runs when WORKFLOW_VERCEL_PROJECT does not start with prj_ or when WORKFLOW_VERCEL_PROJECT_NAME is missing, ensuring consistent normalization regardless of how the env vars were initially populated.

@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from a4be5e8 to 53d573eCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/encryptor-interface branch from 30fc9e5 to fc25b9cCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from 2746c5a to c6af179CompareFebruary 16, 2026 07:56

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but comment is changelog is off

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems off. The actual code doesn't change projectId at all. It seems more like:

Suggested change
Fix `projectConfig.projectId` to contain the real project ID instead of the project name
In UI, show project name instead in ID when available

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's not a UI change. In the world-vercel projectConfig, the projectId was previously being set to the project slug, not the ID.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the changeset description to: "Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)"

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is a clean and well-scoped fix. The separation of project ID vs project name/slug is the right approach. Two items to address:

  1. Connection status UI regression: packages/web/app/components/display-utils/connection-status.tsx:33 reads publicEnv.WORKFLOW_VERCEL_PROJECT to display the connection info string (e.g. team/project). Since WORKFLOW_VERCEL_PROJECT now contains the opaque prj_xxx ID, this will show IDs instead of friendly names. Should be updated to prefer WORKFLOW_VERCEL_PROJECT_NAME, same pattern as packages/cli/src/lib/inspect/web.ts:101-102:
constproject=publicEnv.WORKFLOW_VERCEL_PROJECT_NAME||publicEnv.WORKFLOW_VERCEL_PROJECT;

The Vercel bot flagged this as well.

  1. Changeset description is misleading (see inline comment).

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @VaguelySerious — the changeset description is misleading. The PR doesn't change what projectConfig.projectId contains (it was always the real project ID from .vercel/project.json). The actual fix is that WORKFLOW_VERCEL_PROJECT env var now correctly stores the real project ID instead of the project name/slug, and a new WORKFLOW_VERCEL_PROJECT_NAME env var is introduced for the slug.

Suggested:

Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — used your suggested wording.

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a broader pass across the codebase for project ID/name consistency. A few more things beyond my earlier review:

Naming inconsistency: WORKFLOW_VERCEL_PROJECT_SLUG vs WORKFLOW_VERCEL_PROJECT_NAME

CI already defines a third env var — WORKFLOW_VERCEL_PROJECT_SLUG — used in tests.yml:268, benchmarks.yml:397, and consumed by e2e tests (packages/core/e2e/e2e.test.ts:62) and benchmarks (packages/core/e2e/bench.bench.ts:156). This PR introduces WORKFLOW_VERCEL_PROJECT_NAME for the same concept. That's now two env vars for the project slug/name. Worth unifying on one name (probably WORKFLOW_VERCEL_PROJECT_NAME since it's the new standard) and updating CI + e2e tests to match, or at minimum documenting the relationship.

--project CLI flag can accept a slug

In packages/cli/src/lib/inspect/flags.ts:52-61, the --project flag maps directly to WORKFLOW_VERCEL_PROJECT. Its description says "the vercel project to authenticate against" — users could reasonably pass a slug here. In setup.ts:78, this value is written straight to WORKFLOW_VERCEL_PROJECTbeforeinferVercelEnvVars() runs. Since inferVercelEnvVars() only triggers when WORKFLOW_VERCEL_PROJECT is empty (line 188), a user-provided slug would persist as the "project ID" and get sent in the x-vercel-project-id header — reintroducing the original bug. This is the same concern Copilot raised. Consider either:

  • Normalizing in inferVercelEnvVars even when the env var is already set (e.g., if it doesn't start with prj_)
  • Or splitting the flag into --project-id and --project-name

projectName is carried but never consumed in world-vercel

The APIConfig.projectConfig.projectName field was added to the type in packages/world-vercel/src/utils.ts:40, but getHeaders() (line 173) and getHttpUrl() (line 155) never read it — only projectId and teamId are used for headers and proxy routing. This is fine since it's only for display, but a doc note clarifying it's not sent to the server would help future readers.

// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard on line 188 (!envVars.WORKFLOW_VERCEL_PROJECT || !envVars.WORKFLOW_VERCEL_TEAM) means inference is skipped entirely when both are already set. But WORKFLOW_VERCEL_PROJECT could contain a slug from the --project CLI flag (see flags.ts:58 and setup.ts:78), and WORKFLOW_VERCEL_PROJECT_NAME would remain empty.

Consider also running normalization when WORKFLOW_VERCEL_PROJECT is set but doesn't look like a real project ID (e.g., doesn't start with prj_), or when WORKFLOW_VERCEL_PROJECT_NAME is missing. This would make the env vars robust regardless of how they were initially populated.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Expanded the guard to also run inference when:

  • WORKFLOW_VERCEL_PROJECT does not start with prj_ (e.g., slug from --project flag)
  • WORKFLOW_VERCEL_PROJECT_NAME is missing

Also changed the team assignment to preserve an explicitly set team (envVars.WORKFLOW_VERCEL_TEAM || teamId) so only missing values get populated during normalization.

Comment threadpackages/core/src/runtime/world.ts Outdated
projectConfig: {
environment: process.env.WORKFLOW_VERCEL_ENV,
projectId: process.env.WORKFLOW_VERCEL_PROJECT,
projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could add a brief comment here (like in env.ts) clarifying the distinction:

projectId: process.env.WORKFLOW_VERCEL_PROJECT,// real ID (prj_xxx)projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,// slug (my-app)

Helps future readers understand the split without needing to trace back to the CLI.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added inline comments clarifying the distinction.

@github-actions

github-actionsBot commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.032s (+1.6%)1.005s (~)0.973s101.00x
💻 LocalNitro0.034s (+1.2%)1.005s (~)0.971s101.05x
🌐 RedisNext.js (Turbopack)0.038s1.005s0.967s101.18x
💻 LocalNext.js (Turbopack)0.043s1.004s0.961s101.33x
🌐 MongoDBNext.js (Turbopack)0.100s1.007s0.907s103.10x
🐘 PostgresNitro0.106s (-45.6% 🟢)1.010s (~)0.904s103.26x
🐘 PostgresExpress0.134s (-71.5% 🟢)1.010s (-0.5%)0.876s104.14x
🐘 PostgresNext.js (Turbopack)0.453s1.009s0.557s1013.97x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.513s (-13.6% 🟢)1.784s (-21.4% 🟢)1.271s101.00x
▲ VercelNitro0.684s (-1.0%)2.144s (+2.6%)1.460s101.33x
▲ VercelNext.js (Turbopack)0.979s (+34.7% 🔺)2.389s (+2.1%)1.410s101.91x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.089s2.006s0.918s101.00x
💻 LocalNext.js (Turbopack)1.095s2.005s0.910s101.01x
💻 LocalExpress1.105s (~)2.006s (~)0.900s101.02x
💻 LocalNitro1.112s (~)2.005s (~)0.893s101.02x
🌐 MongoDBNext.js (Turbopack)1.309s2.009s0.700s101.20x
🐘 PostgresNext.js (Turbopack)1.841s2.011s0.171s101.69x
🐘 PostgresExpress2.456s (+3.2%)3.014s (~)0.558s102.26x
🐘 PostgresNitro2.495s (+18.5% 🔺)3.013s (+3.4%)0.518s102.29x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.226s (-2.3%)3.401s (-4.2%)1.175s101.00x
▲ VercelNext.js (Turbopack)2.332s (+5.3% 🔺)3.767s (+7.6% 🔺)1.435s101.05x
▲ VercelNitro2.802s (+22.8% 🔺)4.038s (+28.6% 🔺)1.236s101.26x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)10.594s11.022s0.429s31.00x
💻 LocalNext.js (Turbopack)10.697s11.020s0.323s31.01x
💻 LocalExpress10.819s (~)11.023s (~)0.203s31.02x
💻 LocalNitro10.887s (~)11.024s (~)0.137s31.03x
🌐 MongoDBNext.js (Turbopack)12.341s13.022s0.680s31.16x
🐘 PostgresNext.js (Turbopack)15.273s16.043s0.771s21.44x
🐘 PostgresExpress20.327s (~)21.059s (~)0.732s21.92x
🐘 PostgresNitro20.388s (+32.0% 🔺)21.054s (+31.2% 🔺)0.666s21.92x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express17.270s (+0.9%)18.449s (+3.7%)1.179s21.00x
▲ VercelNext.js (Turbopack)17.501s (-2.8%)18.877s (-1.6%)1.376s21.01x
▲ VercelNitro18.538s (+5.0% 🔺)19.543s (+5.2% 🔺)1.005s21.07x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)26.563s27.051s0.488s31.00x
💻 LocalNext.js (Turbopack)27.133s28.048s0.915s31.02x
💻 LocalExpress27.473s (~)28.050s (~)0.577s31.03x
💻 LocalNitro27.607s (~)28.053s (~)0.446s31.04x
🌐 MongoDBNext.js (Turbopack)30.649s31.045s0.396s21.15x
🐘 PostgresNext.js (Turbopack)37.630s38.089s0.459s21.42x
🐘 PostgresNitro50.155s (+32.8% 🔺)50.622s (+32.9% 🔺)0.467s21.89x
🐘 PostgresExpress50.347s (~)51.133s (~)0.785s21.90x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express43.009s (-4.6%)45.845s (-2.6%)2.836s21.00x
▲ VercelNext.js (Turbopack)43.117s (-4.7%)44.092s (-4.4%)0.974s21.00x
▲ VercelNitro43.536s (+3.7%)45.021s (+3.7%)1.485s21.01x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)53.737s54.099s0.362s21.00x
💻 LocalNext.js (Turbopack)56.586s57.096s0.511s21.05x
💻 LocalExpress57.392s (~)58.101s (~)0.709s21.07x
💻 LocalNitro57.471s (~)58.104s (~)0.632s21.07x
🌐 MongoDBNext.js (Turbopack)61.136s61.582s0.446s21.14x
🐘 PostgresExpress75.430s (-24.7% 🟢)76.181s (-24.0% 🟢)0.750s21.40x
🐘 PostgresNext.js (Turbopack)75.573s76.172s0.599s21.41x
🐘 PostgresNitro77.254s (+2.4%)77.669s (+1.9%)0.415s21.44x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro86.156s (~)87.467s (~)1.311s21.00x
▲ VercelNext.js (Turbopack)87.287s (-1.0%)88.401s (-1.0%)1.113s21.01x
▲ VercelExpress92.167s (+6.0% 🔺)92.965s (+5.8% 🔺)0.798s11.07x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.209s2.006s0.797s151.00x
💻 LocalNext.js (Turbopack)1.377s2.004s0.627s151.14x
💻 LocalNitro1.406s (-2.3%)2.006s (~)0.599s151.16x
💻 LocalExpress1.412s (~)2.005s (~)0.593s151.17x
🐘 PostgresNext.js (Turbopack)1.929s2.226s0.297s141.59x
🐘 PostgresExpress2.002s (-11.5% 🟢)2.682s (-11.0% 🟢)0.681s121.66x
🌐 MongoDBNext.js (Turbopack)2.158s3.008s0.851s101.78x
🐘 PostgresNitro2.276s (+6.7% 🔺)3.015s (+10.0% 🔺)0.738s101.88x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.395s (-0.7%)3.370s (-3.1%)0.974s91.00x
▲ VercelNitro2.424s (-1.3%)3.783s (+7.5% 🔺)1.359s81.01x
▲ VercelNext.js (Turbopack)2.836s (+11.2% 🔺)3.768s (-1.6%)0.932s81.18x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.403s3.008s0.605s101.00x
💻 LocalNitro2.526s (-3.2%)3.008s (~)0.481s101.05x
💻 LocalNext.js (Turbopack)2.541s3.007s0.466s101.06x
💻 LocalExpress2.581s (-1.1%)3.006s (~)0.425s101.07x
🌐 MongoDBNext.js (Turbopack)4.693s5.178s0.485s61.95x
🐘 PostgresNitro6.872s (-35.7% 🟢)7.226s (-34.5% 🟢)0.354s52.86x
🐘 PostgresExpress10.043s (+7.1% 🔺)10.367s (+8.7% 🔺)0.323s34.18x
🐘 PostgresNext.js (Turbopack)10.800s11.367s0.567s34.49x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.567s (-12.0% 🟢)3.862s (-3.6%)1.295s81.00x
▲ VercelNext.js (Turbopack)2.701s (-21.9% 🟢)4.004s (-14.7% 🟢)1.304s81.05x
▲ VercelExpress3.794s (+21.5% 🔺)5.064s (+25.7% 🔺)1.271s61.48x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.929s4.135s0.206s81.00x
💻 LocalNitro7.258s (-3.1%)8.019s (~)0.762s41.85x
💻 LocalExpress7.423s (-1.3%)8.016s (~)0.593s41.89x
💻 LocalNext.js (Turbopack)7.486s7.769s0.282s41.91x
🌐 MongoDBNext.js (Turbopack)9.727s10.352s0.625s32.48x
🐘 PostgresExpress47.361s (-2.2%)48.107s (-2.1%)0.746s112.05x
🐘 PostgresNitro48.096s (-5.7% 🟢)48.117s (-5.9% 🟢)0.021s112.24x
🐘 PostgresNext.js (Turbopack)49.877s50.116s0.239s112.70x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.192s (~)4.148s (-10.5% 🟢)0.955s81.00x
▲ VercelExpress3.249s (-26.1% 🟢)4.185s (-32.5% 🟢)0.935s81.02x
▲ VercelNext.js (Turbopack)3.799s (-58.3% 🟢)5.156s (-48.1% 🟢)1.357s61.19x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.210s2.006s0.796s151.00x
💻 LocalExpress1.417s (-1.1%)2.006s (~)0.588s151.17x
💻 LocalNext.js (Turbopack)1.427s2.005s0.578s151.18x
💻 LocalNitro1.461s (+2.2%)2.006s (~)0.545s151.21x
🐘 PostgresNitro1.920s (-15.4% 🟢)2.078s (-20.0% 🟢)0.158s151.59x
🐘 PostgresNext.js (Turbopack)2.071s2.596s0.525s121.71x
🐘 PostgresExpress2.108s (-0.9%)2.475s (-15.3% 🟢)0.367s131.74x
🌐 MongoDBNext.js (Turbopack)2.156s3.008s0.853s101.78x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.127s (-74.5% 🟢)3.048s (-68.8% 🟢)0.920s101.00x
▲ VercelNitro2.218s (-69.7% 🟢)3.447s (-59.4% 🟢)1.229s91.04x
▲ VercelNext.js (Turbopack)2.425s (-8.7% 🟢)3.632s (-4.4%)1.207s91.14x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.360s3.008s0.648s101.00x
💻 LocalNext.js (Turbopack)2.599s3.008s0.409s101.10x
💻 LocalNitro2.670s (-1.1%)3.008s (~)0.338s101.13x
💻 LocalExpress2.689s (~)3.008s (~)0.319s101.14x
🌐 MongoDBNext.js (Turbopack)4.703s5.177s0.474s61.99x
🐘 PostgresNitro11.509s (+6.1% 🔺)12.370s (+5.7% 🔺)0.861s34.88x
🐘 PostgresNext.js (Turbopack)11.704s12.364s0.660s34.96x
🐘 PostgresExpress12.371s (+5.2% 🔺)12.702s (+2.7%)0.331s35.24x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.341s (-13.1% 🟢)3.165s (-22.6% 🟢)0.823s101.00x
▲ VercelNitro2.689s (~)4.346s (+19.2% 🔺)1.657s71.15x
▲ VercelNext.js (Turbopack)2.839s (-0.9%)3.983s (+4.1%)1.144s91.21x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.889s4.260s0.371s81.00x
💻 LocalNitro7.545s (-6.3% 🟢)8.020s (-5.9% 🟢)0.476s41.94x
💻 LocalNext.js (Turbopack)7.895s8.267s0.372s42.03x
💻 LocalExpress8.148s (+3.1%)9.024s (+2.9%)0.876s42.10x
🌐 MongoDBNext.js (Turbopack)9.732s10.351s0.619s32.50x
🐘 PostgresExpress49.140s (-3.9%)50.108s (-3.9%)0.968s112.64x
🐘 PostgresNitro53.097s (+1.9%)53.121s (~)0.024s113.65x
🐘 PostgresNext.js (Turbopack)56.257s57.116s0.859s114.47x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.627s (-24.6% 🟢)3.580s (-19.0% 🟢)0.953s91.00x
▲ VercelNext.js (Turbopack)3.118s (-31.2% 🟢)4.557s (-17.8% 🟢)1.439s71.19x
▲ VercelNitro4.048s (+34.3% 🔺)5.250s (+32.1% 🔺)1.202s61.54x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)0.110s1.000s0.001s1.007s0.896s101.00x
💻 LocalNext.js (Turbopack)0.140s1.001s0.011s1.016s0.876s101.27x
💻 LocalExpress0.173s (~)1.002s (~)0.011s (+7.5% 🔺)1.017s (~)0.844s101.57x
💻 LocalNitro0.188s (+0.6%)1.002s (~)0.010s (-15.8% 🟢)1.016s (~)0.828s101.71x
🌐 MongoDBNext.js (Turbopack)0.500s0.949s0.001s1.009s0.509s104.53x
🐘 PostgresExpress1.291s (-44.9% 🟢)1.831s (-32.2% 🟢)0.002s (+25.0% 🔺)2.013s (-33.2% 🟢)0.722s1011.70x
🐘 PostgresNext.js (Turbopack)1.391s1.655s0.001s2.013s0.622s1012.61x
🐘 PostgresNitro1.413s (+16.4% 🔺)1.694s (-7.1% 🟢)0.002s (+7.1% 🔺)2.012s (~)0.600s1012.81x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.016s (+3.0%)2.886s (+3.6%)0.164s (-66.7% 🟢)3.607s (-5.7% 🟢)1.591s101.00x
▲ VercelNitro2.051s (+7.7% 🔺)2.772s (-19.8% 🟢)0.545s (+310.7% 🔺)3.939s (-4.5%)1.888s101.02x
▲ VercelExpress2.080s (+5.0% 🔺)2.771s (~)0.660s (+212.5% 🔺)3.916s (+10.5% 🔺)1.836s101.03x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)7/12
🐘 PostgresNitro4/12
▲ VercelExpress8/12
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express💻 Local9/12
Next.js (Turbopack)🌐 Redis10/12
Nitro💻 Local10/12
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TooTallNate@pranaygp@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fix projectConfig.projectId containing project name instead of ID - #999

Merged
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config
Feb 18, 2026
Merged

Fix projectConfig.projectId containing project name instead of ID#999
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Feb 11, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes WORKFLOW_VERCEL_PROJECT env var to contain the real project ID instead of the project name/slug
  • Adds WORKFLOW_VERCEL_PROJECT_NAME for the project slug

@github-actions

github-actionsBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production534038572
✅ 💻 Local Development556068624
✅ 📦 Local Production556068624
✅ 🐘 Local Postgres556068624
✅ 🪟 Windows490352
❌ 🌍 Community Worlds111459165
✅ 📋 Other135021156
Total2497452752817

❌ Failed Tests

🌍 Community Worlds (45 failed)

turso (45 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • parallelSleepWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling retry behavior workflow completes despite transient 5xx on step_completed
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument
  • cancelRun - cancelling a running workflow
  • cancelRun via CLI - cancelling a running workflow
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro4804
✅ example4804
✅ express4804
✅ fastify4804
✅ hono4804
✅ nextjs-turbopack5101
✅ nextjs-webpack5101
✅ nitro4804
✅ nuxt4804
✅ sveltekit4804
✅ vite4804
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack4903
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev300
✅ mongodb4903
✅ redis-dev300
✅ redis4903
✅ turso-dev300
❌ turso4453
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable4507
✅ e2e-local-postgres-nest-stable4507
✅ e2e-local-prod-nest-stable4507

📋 View full workflow run

@changeset-bot

changeset-botBot commented Feb 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2a6cf4b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
@workflow/world-vercelPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/web-sharedPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNate marked this pull request as ready for review February 11, 2026 04:18
CopilotAI review requested due to automatic review settings February 11, 2026 04:18

@vercelvercelBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

Connection status UI displays opaque Vercel project ID (e.g., prj_xxx) instead of the human-readable project name after WORKFLOW_VERCEL_PROJECT was changed to store the real project ID.

Fix on Vercel

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes inconsistent handling of Vercel project identity by separating the project ID (used for API/auth/encryption contexts) from the project slug/name (used for dashboard URLs and display), and wires the new env var through CLI, core runtime, and the web server’s Vercel world creation path.

Changes:

  • Added WORKFLOW_VERCEL_PROJECT_NAME (project slug/name) alongside WORKFLOW_VERCEL_PROJECT (real prj_… id).
  • Updated CLI env inference to set WORKFLOW_VERCEL_PROJECT to the true project ID and populate the new project-name env var.
  • Plumbed projectName through core/runtime world creation and web server env allowlists / Vercel world instantiation.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
packages/world-vercel/src/utils.tsExtends Vercel world config typing to include both project ID and project slug/name.
packages/web/src/server/workflow-server-actions.tsAllows the new env var to reach the client and passes it into createVercelWorld().
packages/core/src/runtime/world.tsAdds WORKFLOW_VERCEL_PROJECT_NAME into the runtime’s Vercel world config.
packages/cli/src/lib/inspect/web.tsUses project slug/name (when available) for dashboard URL generation.
packages/cli/src/lib/inspect/env.tsAdds the new env var and updates Vercel env inference to distinguish ID vs name.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 203 to +207
'WORKFLOW_TARGET_WORLD',
'WORKFLOW_VERCEL_ENV',
'WORKFLOW_VERCEL_TEAM',
'WORKFLOW_VERCEL_PROJECT',
'WORKFLOW_VERCEL_PROJECT_NAME',

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says the web UI was updated to prefer the Vercel project name/slug when available, but the only consumer updated here appears to be the CLI dashboard URL logic. The web UI still appears to read/display WORKFLOW_VERCEL_PROJECT (now intended to be the prj_… id), so the UI may show IDs instead of friendly slugs unless the client-side components are updated to use WORKFLOW_VERCEL_PROJECT_NAME.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web UI path changed significantly during the React Router refactor. The web server actions now use createVercelWorld() which receives projectConfig with both projectId and projectName. The dashboard URL logic uses the name/slug.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web server actions use createVercelWorld() which receives both projectId and projectName via projectConfig. The dashboard URL uses the name/slug. No additional web UI changes needed.

Comment on lines +193 to +196
// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inferVercelEnvVars() only populates WORKFLOW_VERCEL_PROJECT_NAME (and normalizes WORKFLOW_VERCEL_PROJECT to a real prj_… id) when either WORKFLOW_VERCEL_PROJECT or WORKFLOW_VERCEL_TEAM is missing. If the CLI flag/env already sets WORKFLOW_VERCEL_PROJECT to a project slug/name (which the --project flag description currently implies), this block won’t run, and the world will continue sending the slug in the x-vercel-project-id header—reintroducing the exact bug this PR is fixing and potentially breaking auth/encryption context. Consider expanding the guard to also run when WORKFLOW_VERCEL_PROJECT_NAME is missing and/or when WORKFLOW_VERCEL_PROJECT doesn’t look like a Vercel project id (e.g. not prj_…), so the env vars are consistently normalized.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inference logic normalizes the env var to a real project ID when the linked project is available. If the user sets WORKFLOW_VERCEL_PROJECT to a slug, the inference step replaces it with the real ID from .vercel/project.json.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the guard now also runs when WORKFLOW_VERCEL_PROJECT does not start with prj_ or when WORKFLOW_VERCEL_PROJECT_NAME is missing, ensuring consistent normalization regardless of how the env vars were initially populated.

@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from a4be5e8 to 53d573eCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/encryptor-interface branch from 30fc9e5 to fc25b9cCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from 2746c5a to c6af179CompareFebruary 16, 2026 07:56

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but comment is changelog is off

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems off. The actual code doesn't change projectId at all. It seems more like:

Suggested change
Fix `projectConfig.projectId` to contain the real project ID instead of the project name
In UI, show project name instead in ID when available

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's not a UI change. In the world-vercel projectConfig, the projectId was previously being set to the project slug, not the ID.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the changeset description to: "Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)"

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is a clean and well-scoped fix. The separation of project ID vs project name/slug is the right approach. Two items to address:

  1. Connection status UI regression: packages/web/app/components/display-utils/connection-status.tsx:33 reads publicEnv.WORKFLOW_VERCEL_PROJECT to display the connection info string (e.g. team/project). Since WORKFLOW_VERCEL_PROJECT now contains the opaque prj_xxx ID, this will show IDs instead of friendly names. Should be updated to prefer WORKFLOW_VERCEL_PROJECT_NAME, same pattern as packages/cli/src/lib/inspect/web.ts:101-102:
constproject=publicEnv.WORKFLOW_VERCEL_PROJECT_NAME||publicEnv.WORKFLOW_VERCEL_PROJECT;

The Vercel bot flagged this as well.

  1. Changeset description is misleading (see inline comment).

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @VaguelySerious — the changeset description is misleading. The PR doesn't change what projectConfig.projectId contains (it was always the real project ID from .vercel/project.json). The actual fix is that WORKFLOW_VERCEL_PROJECT env var now correctly stores the real project ID instead of the project name/slug, and a new WORKFLOW_VERCEL_PROJECT_NAME env var is introduced for the slug.

Suggested:

Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — used your suggested wording.

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a broader pass across the codebase for project ID/name consistency. A few more things beyond my earlier review:

Naming inconsistency: WORKFLOW_VERCEL_PROJECT_SLUG vs WORKFLOW_VERCEL_PROJECT_NAME

CI already defines a third env var — WORKFLOW_VERCEL_PROJECT_SLUG — used in tests.yml:268, benchmarks.yml:397, and consumed by e2e tests (packages/core/e2e/e2e.test.ts:62) and benchmarks (packages/core/e2e/bench.bench.ts:156). This PR introduces WORKFLOW_VERCEL_PROJECT_NAME for the same concept. That's now two env vars for the project slug/name. Worth unifying on one name (probably WORKFLOW_VERCEL_PROJECT_NAME since it's the new standard) and updating CI + e2e tests to match, or at minimum documenting the relationship.

--project CLI flag can accept a slug

In packages/cli/src/lib/inspect/flags.ts:52-61, the --project flag maps directly to WORKFLOW_VERCEL_PROJECT. Its description says "the vercel project to authenticate against" — users could reasonably pass a slug here. In setup.ts:78, this value is written straight to WORKFLOW_VERCEL_PROJECTbeforeinferVercelEnvVars() runs. Since inferVercelEnvVars() only triggers when WORKFLOW_VERCEL_PROJECT is empty (line 188), a user-provided slug would persist as the "project ID" and get sent in the x-vercel-project-id header — reintroducing the original bug. This is the same concern Copilot raised. Consider either:

  • Normalizing in inferVercelEnvVars even when the env var is already set (e.g., if it doesn't start with prj_)
  • Or splitting the flag into --project-id and --project-name

projectName is carried but never consumed in world-vercel

The APIConfig.projectConfig.projectName field was added to the type in packages/world-vercel/src/utils.ts:40, but getHeaders() (line 173) and getHttpUrl() (line 155) never read it — only projectId and teamId are used for headers and proxy routing. This is fine since it's only for display, but a doc note clarifying it's not sent to the server would help future readers.

// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard on line 188 (!envVars.WORKFLOW_VERCEL_PROJECT || !envVars.WORKFLOW_VERCEL_TEAM) means inference is skipped entirely when both are already set. But WORKFLOW_VERCEL_PROJECT could contain a slug from the --project CLI flag (see flags.ts:58 and setup.ts:78), and WORKFLOW_VERCEL_PROJECT_NAME would remain empty.

Consider also running normalization when WORKFLOW_VERCEL_PROJECT is set but doesn't look like a real project ID (e.g., doesn't start with prj_), or when WORKFLOW_VERCEL_PROJECT_NAME is missing. This would make the env vars robust regardless of how they were initially populated.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Expanded the guard to also run inference when:

  • WORKFLOW_VERCEL_PROJECT does not start with prj_ (e.g., slug from --project flag)
  • WORKFLOW_VERCEL_PROJECT_NAME is missing

Also changed the team assignment to preserve an explicitly set team (envVars.WORKFLOW_VERCEL_TEAM || teamId) so only missing values get populated during normalization.

Comment threadpackages/core/src/runtime/world.ts Outdated
projectConfig: {
environment: process.env.WORKFLOW_VERCEL_ENV,
projectId: process.env.WORKFLOW_VERCEL_PROJECT,
projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could add a brief comment here (like in env.ts) clarifying the distinction:

projectId: process.env.WORKFLOW_VERCEL_PROJECT,// real ID (prj_xxx)projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,// slug (my-app)

Helps future readers understand the split without needing to trace back to the CLI.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added inline comments clarifying the distinction.

@github-actions

github-actionsBot commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.032s (+1.6%)1.005s (~)0.973s101.00x
💻 LocalNitro0.034s (+1.2%)1.005s (~)0.971s101.05x
🌐 RedisNext.js (Turbopack)0.038s1.005s0.967s101.18x
💻 LocalNext.js (Turbopack)0.043s1.004s0.961s101.33x
🌐 MongoDBNext.js (Turbopack)0.100s1.007s0.907s103.10x
🐘 PostgresNitro0.106s (-45.6% 🟢)1.010s (~)0.904s103.26x
🐘 PostgresExpress0.134s (-71.5% 🟢)1.010s (-0.5%)0.876s104.14x
🐘 PostgresNext.js (Turbopack)0.453s1.009s0.557s1013.97x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.513s (-13.6% 🟢)1.784s (-21.4% 🟢)1.271s101.00x
▲ VercelNitro0.684s (-1.0%)2.144s (+2.6%)1.460s101.33x
▲ VercelNext.js (Turbopack)0.979s (+34.7% 🔺)2.389s (+2.1%)1.410s101.91x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.089s2.006s0.918s101.00x
💻 LocalNext.js (Turbopack)1.095s2.005s0.910s101.01x
💻 LocalExpress1.105s (~)2.006s (~)0.900s101.02x
💻 LocalNitro1.112s (~)2.005s (~)0.893s101.02x
🌐 MongoDBNext.js (Turbopack)1.309s2.009s0.700s101.20x
🐘 PostgresNext.js (Turbopack)1.841s2.011s0.171s101.69x
🐘 PostgresExpress2.456s (+3.2%)3.014s (~)0.558s102.26x
🐘 PostgresNitro2.495s (+18.5% 🔺)3.013s (+3.4%)0.518s102.29x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.226s (-2.3%)3.401s (-4.2%)1.175s101.00x
▲ VercelNext.js (Turbopack)2.332s (+5.3% 🔺)3.767s (+7.6% 🔺)1.435s101.05x
▲ VercelNitro2.802s (+22.8% 🔺)4.038s (+28.6% 🔺)1.236s101.26x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)10.594s11.022s0.429s31.00x
💻 LocalNext.js (Turbopack)10.697s11.020s0.323s31.01x
💻 LocalExpress10.819s (~)11.023s (~)0.203s31.02x
💻 LocalNitro10.887s (~)11.024s (~)0.137s31.03x
🌐 MongoDBNext.js (Turbopack)12.341s13.022s0.680s31.16x
🐘 PostgresNext.js (Turbopack)15.273s16.043s0.771s21.44x
🐘 PostgresExpress20.327s (~)21.059s (~)0.732s21.92x
🐘 PostgresNitro20.388s (+32.0% 🔺)21.054s (+31.2% 🔺)0.666s21.92x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express17.270s (+0.9%)18.449s (+3.7%)1.179s21.00x
▲ VercelNext.js (Turbopack)17.501s (-2.8%)18.877s (-1.6%)1.376s21.01x
▲ VercelNitro18.538s (+5.0% 🔺)19.543s (+5.2% 🔺)1.005s21.07x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)26.563s27.051s0.488s31.00x
💻 LocalNext.js (Turbopack)27.133s28.048s0.915s31.02x
💻 LocalExpress27.473s (~)28.050s (~)0.577s31.03x
💻 LocalNitro27.607s (~)28.053s (~)0.446s31.04x
🌐 MongoDBNext.js (Turbopack)30.649s31.045s0.396s21.15x
🐘 PostgresNext.js (Turbopack)37.630s38.089s0.459s21.42x
🐘 PostgresNitro50.155s (+32.8% 🔺)50.622s (+32.9% 🔺)0.467s21.89x
🐘 PostgresExpress50.347s (~)51.133s (~)0.785s21.90x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express43.009s (-4.6%)45.845s (-2.6%)2.836s21.00x
▲ VercelNext.js (Turbopack)43.117s (-4.7%)44.092s (-4.4%)0.974s21.00x
▲ VercelNitro43.536s (+3.7%)45.021s (+3.7%)1.485s21.01x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)53.737s54.099s0.362s21.00x
💻 LocalNext.js (Turbopack)56.586s57.096s0.511s21.05x
💻 LocalExpress57.392s (~)58.101s (~)0.709s21.07x
💻 LocalNitro57.471s (~)58.104s (~)0.632s21.07x
🌐 MongoDBNext.js (Turbopack)61.136s61.582s0.446s21.14x
🐘 PostgresExpress75.430s (-24.7% 🟢)76.181s (-24.0% 🟢)0.750s21.40x
🐘 PostgresNext.js (Turbopack)75.573s76.172s0.599s21.41x
🐘 PostgresNitro77.254s (+2.4%)77.669s (+1.9%)0.415s21.44x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro86.156s (~)87.467s (~)1.311s21.00x
▲ VercelNext.js (Turbopack)87.287s (-1.0%)88.401s (-1.0%)1.113s21.01x
▲ VercelExpress92.167s (+6.0% 🔺)92.965s (+5.8% 🔺)0.798s11.07x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.209s2.006s0.797s151.00x
💻 LocalNext.js (Turbopack)1.377s2.004s0.627s151.14x
💻 LocalNitro1.406s (-2.3%)2.006s (~)0.599s151.16x
💻 LocalExpress1.412s (~)2.005s (~)0.593s151.17x
🐘 PostgresNext.js (Turbopack)1.929s2.226s0.297s141.59x
🐘 PostgresExpress2.002s (-11.5% 🟢)2.682s (-11.0% 🟢)0.681s121.66x
🌐 MongoDBNext.js (Turbopack)2.158s3.008s0.851s101.78x
🐘 PostgresNitro2.276s (+6.7% 🔺)3.015s (+10.0% 🔺)0.738s101.88x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.395s (-0.7%)3.370s (-3.1%)0.974s91.00x
▲ VercelNitro2.424s (-1.3%)3.783s (+7.5% 🔺)1.359s81.01x
▲ VercelNext.js (Turbopack)2.836s (+11.2% 🔺)3.768s (-1.6%)0.932s81.18x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.403s3.008s0.605s101.00x
💻 LocalNitro2.526s (-3.2%)3.008s (~)0.481s101.05x
💻 LocalNext.js (Turbopack)2.541s3.007s0.466s101.06x
💻 LocalExpress2.581s (-1.1%)3.006s (~)0.425s101.07x
🌐 MongoDBNext.js (Turbopack)4.693s5.178s0.485s61.95x
🐘 PostgresNitro6.872s (-35.7% 🟢)7.226s (-34.5% 🟢)0.354s52.86x
🐘 PostgresExpress10.043s (+7.1% 🔺)10.367s (+8.7% 🔺)0.323s34.18x
🐘 PostgresNext.js (Turbopack)10.800s11.367s0.567s34.49x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.567s (-12.0% 🟢)3.862s (-3.6%)1.295s81.00x
▲ VercelNext.js (Turbopack)2.701s (-21.9% 🟢)4.004s (-14.7% 🟢)1.304s81.05x
▲ VercelExpress3.794s (+21.5% 🔺)5.064s (+25.7% 🔺)1.271s61.48x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.929s4.135s0.206s81.00x
💻 LocalNitro7.258s (-3.1%)8.019s (~)0.762s41.85x
💻 LocalExpress7.423s (-1.3%)8.016s (~)0.593s41.89x
💻 LocalNext.js (Turbopack)7.486s7.769s0.282s41.91x
🌐 MongoDBNext.js (Turbopack)9.727s10.352s0.625s32.48x
🐘 PostgresExpress47.361s (-2.2%)48.107s (-2.1%)0.746s112.05x
🐘 PostgresNitro48.096s (-5.7% 🟢)48.117s (-5.9% 🟢)0.021s112.24x
🐘 PostgresNext.js (Turbopack)49.877s50.116s0.239s112.70x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.192s (~)4.148s (-10.5% 🟢)0.955s81.00x
▲ VercelExpress3.249s (-26.1% 🟢)4.185s (-32.5% 🟢)0.935s81.02x
▲ VercelNext.js (Turbopack)3.799s (-58.3% 🟢)5.156s (-48.1% 🟢)1.357s61.19x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.210s2.006s0.796s151.00x
💻 LocalExpress1.417s (-1.1%)2.006s (~)0.588s151.17x
💻 LocalNext.js (Turbopack)1.427s2.005s0.578s151.18x
💻 LocalNitro1.461s (+2.2%)2.006s (~)0.545s151.21x
🐘 PostgresNitro1.920s (-15.4% 🟢)2.078s (-20.0% 🟢)0.158s151.59x
🐘 PostgresNext.js (Turbopack)2.071s2.596s0.525s121.71x
🐘 PostgresExpress2.108s (-0.9%)2.475s (-15.3% 🟢)0.367s131.74x
🌐 MongoDBNext.js (Turbopack)2.156s3.008s0.853s101.78x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.127s (-74.5% 🟢)3.048s (-68.8% 🟢)0.920s101.00x
▲ VercelNitro2.218s (-69.7% 🟢)3.447s (-59.4% 🟢)1.229s91.04x
▲ VercelNext.js (Turbopack)2.425s (-8.7% 🟢)3.632s (-4.4%)1.207s91.14x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.360s3.008s0.648s101.00x
💻 LocalNext.js (Turbopack)2.599s3.008s0.409s101.10x
💻 LocalNitro2.670s (-1.1%)3.008s (~)0.338s101.13x
💻 LocalExpress2.689s (~)3.008s (~)0.319s101.14x
🌐 MongoDBNext.js (Turbopack)4.703s5.177s0.474s61.99x
🐘 PostgresNitro11.509s (+6.1% 🔺)12.370s (+5.7% 🔺)0.861s34.88x
🐘 PostgresNext.js (Turbopack)11.704s12.364s0.660s34.96x
🐘 PostgresExpress12.371s (+5.2% 🔺)12.702s (+2.7%)0.331s35.24x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.341s (-13.1% 🟢)3.165s (-22.6% 🟢)0.823s101.00x
▲ VercelNitro2.689s (~)4.346s (+19.2% 🔺)1.657s71.15x
▲ VercelNext.js (Turbopack)2.839s (-0.9%)3.983s (+4.1%)1.144s91.21x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.889s4.260s0.371s81.00x
💻 LocalNitro7.545s (-6.3% 🟢)8.020s (-5.9% 🟢)0.476s41.94x
💻 LocalNext.js (Turbopack)7.895s8.267s0.372s42.03x
💻 LocalExpress8.148s (+3.1%)9.024s (+2.9%)0.876s42.10x
🌐 MongoDBNext.js (Turbopack)9.732s10.351s0.619s32.50x
🐘 PostgresExpress49.140s (-3.9%)50.108s (-3.9%)0.968s112.64x
🐘 PostgresNitro53.097s (+1.9%)53.121s (~)0.024s113.65x
🐘 PostgresNext.js (Turbopack)56.257s57.116s0.859s114.47x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.627s (-24.6% 🟢)3.580s (-19.0% 🟢)0.953s91.00x
▲ VercelNext.js (Turbopack)3.118s (-31.2% 🟢)4.557s (-17.8% 🟢)1.439s71.19x
▲ VercelNitro4.048s (+34.3% 🔺)5.250s (+32.1% 🔺)1.202s61.54x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)0.110s1.000s0.001s1.007s0.896s101.00x
💻 LocalNext.js (Turbopack)0.140s1.001s0.011s1.016s0.876s101.27x
💻 LocalExpress0.173s (~)1.002s (~)0.011s (+7.5% 🔺)1.017s (~)0.844s101.57x
💻 LocalNitro0.188s (+0.6%)1.002s (~)0.010s (-15.8% 🟢)1.016s (~)0.828s101.71x
🌐 MongoDBNext.js (Turbopack)0.500s0.949s0.001s1.009s0.509s104.53x
🐘 PostgresExpress1.291s (-44.9% 🟢)1.831s (-32.2% 🟢)0.002s (+25.0% 🔺)2.013s (-33.2% 🟢)0.722s1011.70x
🐘 PostgresNext.js (Turbopack)1.391s1.655s0.001s2.013s0.622s1012.61x
🐘 PostgresNitro1.413s (+16.4% 🔺)1.694s (-7.1% 🟢)0.002s (+7.1% 🔺)2.012s (~)0.600s1012.81x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.016s (+3.0%)2.886s (+3.6%)0.164s (-66.7% 🟢)3.607s (-5.7% 🟢)1.591s101.00x
▲ VercelNitro2.051s (+7.7% 🔺)2.772s (-19.8% 🟢)0.545s (+310.7% 🔺)3.939s (-4.5%)1.888s101.02x
▲ VercelExpress2.080s (+5.0% 🔺)2.771s (~)0.660s (+212.5% 🔺)3.916s (+10.5% 🔺)1.836s101.03x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)7/12
🐘 PostgresNitro4/12
▲ VercelExpress8/12
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express💻 Local9/12
Next.js (Turbopack)🌐 Redis10/12
Nitro💻 Local10/12
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TooTallNate@pranaygp@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix projectConfig.projectId containing project name instead of ID - #999

Merged
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config
Feb 18, 2026
Merged

Fix projectConfig.projectId containing project name instead of ID#999
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Feb 11, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes WORKFLOW_VERCEL_PROJECT env var to contain the real project ID instead of the project name/slug
  • Adds WORKFLOW_VERCEL_PROJECT_NAME for the project slug

@github-actions

github-actionsBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production534038572
✅ 💻 Local Development556068624
✅ 📦 Local Production556068624
✅ 🐘 Local Postgres556068624
✅ 🪟 Windows490352
❌ 🌍 Community Worlds111459165
✅ 📋 Other135021156
Total2497452752817

❌ Failed Tests

🌍 Community Worlds (45 failed)

turso (45 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • parallelSleepWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling retry behavior workflow completes despite transient 5xx on step_completed
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument
  • cancelRun - cancelling a running workflow
  • cancelRun via CLI - cancelling a running workflow
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro4804
✅ example4804
✅ express4804
✅ fastify4804
✅ hono4804
✅ nextjs-turbopack5101
✅ nextjs-webpack5101
✅ nitro4804
✅ nuxt4804
✅ sveltekit4804
✅ vite4804
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack4903
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev300
✅ mongodb4903
✅ redis-dev300
✅ redis4903
✅ turso-dev300
❌ turso4453
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable4507
✅ e2e-local-postgres-nest-stable4507
✅ e2e-local-prod-nest-stable4507

📋 View full workflow run

@changeset-bot

changeset-botBot commented Feb 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2a6cf4b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
@workflow/world-vercelPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/web-sharedPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNate marked this pull request as ready for review February 11, 2026 04:18
CopilotAI review requested due to automatic review settings February 11, 2026 04:18

@vercelvercelBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

Connection status UI displays opaque Vercel project ID (e.g., prj_xxx) instead of the human-readable project name after WORKFLOW_VERCEL_PROJECT was changed to store the real project ID.

Fix on Vercel

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes inconsistent handling of Vercel project identity by separating the project ID (used for API/auth/encryption contexts) from the project slug/name (used for dashboard URLs and display), and wires the new env var through CLI, core runtime, and the web server’s Vercel world creation path.

Changes:

  • Added WORKFLOW_VERCEL_PROJECT_NAME (project slug/name) alongside WORKFLOW_VERCEL_PROJECT (real prj_… id).
  • Updated CLI env inference to set WORKFLOW_VERCEL_PROJECT to the true project ID and populate the new project-name env var.
  • Plumbed projectName through core/runtime world creation and web server env allowlists / Vercel world instantiation.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
packages/world-vercel/src/utils.tsExtends Vercel world config typing to include both project ID and project slug/name.
packages/web/src/server/workflow-server-actions.tsAllows the new env var to reach the client and passes it into createVercelWorld().
packages/core/src/runtime/world.tsAdds WORKFLOW_VERCEL_PROJECT_NAME into the runtime’s Vercel world config.
packages/cli/src/lib/inspect/web.tsUses project slug/name (when available) for dashboard URL generation.
packages/cli/src/lib/inspect/env.tsAdds the new env var and updates Vercel env inference to distinguish ID vs name.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 203 to +207
'WORKFLOW_TARGET_WORLD',
'WORKFLOW_VERCEL_ENV',
'WORKFLOW_VERCEL_TEAM',
'WORKFLOW_VERCEL_PROJECT',
'WORKFLOW_VERCEL_PROJECT_NAME',

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says the web UI was updated to prefer the Vercel project name/slug when available, but the only consumer updated here appears to be the CLI dashboard URL logic. The web UI still appears to read/display WORKFLOW_VERCEL_PROJECT (now intended to be the prj_… id), so the UI may show IDs instead of friendly slugs unless the client-side components are updated to use WORKFLOW_VERCEL_PROJECT_NAME.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web UI path changed significantly during the React Router refactor. The web server actions now use createVercelWorld() which receives projectConfig with both projectId and projectName. The dashboard URL logic uses the name/slug.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web server actions use createVercelWorld() which receives both projectId and projectName via projectConfig. The dashboard URL uses the name/slug. No additional web UI changes needed.

Comment on lines +193 to +196
// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inferVercelEnvVars() only populates WORKFLOW_VERCEL_PROJECT_NAME (and normalizes WORKFLOW_VERCEL_PROJECT to a real prj_… id) when either WORKFLOW_VERCEL_PROJECT or WORKFLOW_VERCEL_TEAM is missing. If the CLI flag/env already sets WORKFLOW_VERCEL_PROJECT to a project slug/name (which the --project flag description currently implies), this block won’t run, and the world will continue sending the slug in the x-vercel-project-id header—reintroducing the exact bug this PR is fixing and potentially breaking auth/encryption context. Consider expanding the guard to also run when WORKFLOW_VERCEL_PROJECT_NAME is missing and/or when WORKFLOW_VERCEL_PROJECT doesn’t look like a Vercel project id (e.g. not prj_…), so the env vars are consistently normalized.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inference logic normalizes the env var to a real project ID when the linked project is available. If the user sets WORKFLOW_VERCEL_PROJECT to a slug, the inference step replaces it with the real ID from .vercel/project.json.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the guard now also runs when WORKFLOW_VERCEL_PROJECT does not start with prj_ or when WORKFLOW_VERCEL_PROJECT_NAME is missing, ensuring consistent normalization regardless of how the env vars were initially populated.

@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from a4be5e8 to 53d573eCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/encryptor-interface branch from 30fc9e5 to fc25b9cCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from 2746c5a to c6af179CompareFebruary 16, 2026 07:56

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but comment is changelog is off

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems off. The actual code doesn't change projectId at all. It seems more like:

Suggested change
Fix `projectConfig.projectId` to contain the real project ID instead of the project name
In UI, show project name instead in ID when available

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's not a UI change. In the world-vercel projectConfig, the projectId was previously being set to the project slug, not the ID.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the changeset description to: "Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)"

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is a clean and well-scoped fix. The separation of project ID vs project name/slug is the right approach. Two items to address:

  1. Connection status UI regression: packages/web/app/components/display-utils/connection-status.tsx:33 reads publicEnv.WORKFLOW_VERCEL_PROJECT to display the connection info string (e.g. team/project). Since WORKFLOW_VERCEL_PROJECT now contains the opaque prj_xxx ID, this will show IDs instead of friendly names. Should be updated to prefer WORKFLOW_VERCEL_PROJECT_NAME, same pattern as packages/cli/src/lib/inspect/web.ts:101-102:
constproject=publicEnv.WORKFLOW_VERCEL_PROJECT_NAME||publicEnv.WORKFLOW_VERCEL_PROJECT;

The Vercel bot flagged this as well.

  1. Changeset description is misleading (see inline comment).

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @VaguelySerious — the changeset description is misleading. The PR doesn't change what projectConfig.projectId contains (it was always the real project ID from .vercel/project.json). The actual fix is that WORKFLOW_VERCEL_PROJECT env var now correctly stores the real project ID instead of the project name/slug, and a new WORKFLOW_VERCEL_PROJECT_NAME env var is introduced for the slug.

Suggested:

Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — used your suggested wording.

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a broader pass across the codebase for project ID/name consistency. A few more things beyond my earlier review:

Naming inconsistency: WORKFLOW_VERCEL_PROJECT_SLUG vs WORKFLOW_VERCEL_PROJECT_NAME

CI already defines a third env var — WORKFLOW_VERCEL_PROJECT_SLUG — used in tests.yml:268, benchmarks.yml:397, and consumed by e2e tests (packages/core/e2e/e2e.test.ts:62) and benchmarks (packages/core/e2e/bench.bench.ts:156). This PR introduces WORKFLOW_VERCEL_PROJECT_NAME for the same concept. That's now two env vars for the project slug/name. Worth unifying on one name (probably WORKFLOW_VERCEL_PROJECT_NAME since it's the new standard) and updating CI + e2e tests to match, or at minimum documenting the relationship.

--project CLI flag can accept a slug

In packages/cli/src/lib/inspect/flags.ts:52-61, the --project flag maps directly to WORKFLOW_VERCEL_PROJECT. Its description says "the vercel project to authenticate against" — users could reasonably pass a slug here. In setup.ts:78, this value is written straight to WORKFLOW_VERCEL_PROJECTbeforeinferVercelEnvVars() runs. Since inferVercelEnvVars() only triggers when WORKFLOW_VERCEL_PROJECT is empty (line 188), a user-provided slug would persist as the "project ID" and get sent in the x-vercel-project-id header — reintroducing the original bug. This is the same concern Copilot raised. Consider either:

  • Normalizing in inferVercelEnvVars even when the env var is already set (e.g., if it doesn't start with prj_)
  • Or splitting the flag into --project-id and --project-name

projectName is carried but never consumed in world-vercel

The APIConfig.projectConfig.projectName field was added to the type in packages/world-vercel/src/utils.ts:40, but getHeaders() (line 173) and getHttpUrl() (line 155) never read it — only projectId and teamId are used for headers and proxy routing. This is fine since it's only for display, but a doc note clarifying it's not sent to the server would help future readers.

// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard on line 188 (!envVars.WORKFLOW_VERCEL_PROJECT || !envVars.WORKFLOW_VERCEL_TEAM) means inference is skipped entirely when both are already set. But WORKFLOW_VERCEL_PROJECT could contain a slug from the --project CLI flag (see flags.ts:58 and setup.ts:78), and WORKFLOW_VERCEL_PROJECT_NAME would remain empty.

Consider also running normalization when WORKFLOW_VERCEL_PROJECT is set but doesn't look like a real project ID (e.g., doesn't start with prj_), or when WORKFLOW_VERCEL_PROJECT_NAME is missing. This would make the env vars robust regardless of how they were initially populated.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Expanded the guard to also run inference when:

  • WORKFLOW_VERCEL_PROJECT does not start with prj_ (e.g., slug from --project flag)
  • WORKFLOW_VERCEL_PROJECT_NAME is missing

Also changed the team assignment to preserve an explicitly set team (envVars.WORKFLOW_VERCEL_TEAM || teamId) so only missing values get populated during normalization.

Comment threadpackages/core/src/runtime/world.ts Outdated
projectConfig: {
environment: process.env.WORKFLOW_VERCEL_ENV,
projectId: process.env.WORKFLOW_VERCEL_PROJECT,
projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could add a brief comment here (like in env.ts) clarifying the distinction:

projectId: process.env.WORKFLOW_VERCEL_PROJECT,// real ID (prj_xxx)projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,// slug (my-app)

Helps future readers understand the split without needing to trace back to the CLI.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added inline comments clarifying the distinction.

@github-actions

github-actionsBot commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.032s (+1.6%)1.005s (~)0.973s101.00x
💻 LocalNitro0.034s (+1.2%)1.005s (~)0.971s101.05x
🌐 RedisNext.js (Turbopack)0.038s1.005s0.967s101.18x
💻 LocalNext.js (Turbopack)0.043s1.004s0.961s101.33x
🌐 MongoDBNext.js (Turbopack)0.100s1.007s0.907s103.10x
🐘 PostgresNitro0.106s (-45.6% 🟢)1.010s (~)0.904s103.26x
🐘 PostgresExpress0.134s (-71.5% 🟢)1.010s (-0.5%)0.876s104.14x
🐘 PostgresNext.js (Turbopack)0.453s1.009s0.557s1013.97x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.513s (-13.6% 🟢)1.784s (-21.4% 🟢)1.271s101.00x
▲ VercelNitro0.684s (-1.0%)2.144s (+2.6%)1.460s101.33x
▲ VercelNext.js (Turbopack)0.979s (+34.7% 🔺)2.389s (+2.1%)1.410s101.91x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.089s2.006s0.918s101.00x
💻 LocalNext.js (Turbopack)1.095s2.005s0.910s101.01x
💻 LocalExpress1.105s (~)2.006s (~)0.900s101.02x
💻 LocalNitro1.112s (~)2.005s (~)0.893s101.02x
🌐 MongoDBNext.js (Turbopack)1.309s2.009s0.700s101.20x
🐘 PostgresNext.js (Turbopack)1.841s2.011s0.171s101.69x
🐘 PostgresExpress2.456s (+3.2%)3.014s (~)0.558s102.26x
🐘 PostgresNitro2.495s (+18.5% 🔺)3.013s (+3.4%)0.518s102.29x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.226s (-2.3%)3.401s (-4.2%)1.175s101.00x
▲ VercelNext.js (Turbopack)2.332s (+5.3% 🔺)3.767s (+7.6% 🔺)1.435s101.05x
▲ VercelNitro2.802s (+22.8% 🔺)4.038s (+28.6% 🔺)1.236s101.26x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)10.594s11.022s0.429s31.00x
💻 LocalNext.js (Turbopack)10.697s11.020s0.323s31.01x
💻 LocalExpress10.819s (~)11.023s (~)0.203s31.02x
💻 LocalNitro10.887s (~)11.024s (~)0.137s31.03x
🌐 MongoDBNext.js (Turbopack)12.341s13.022s0.680s31.16x
🐘 PostgresNext.js (Turbopack)15.273s16.043s0.771s21.44x
🐘 PostgresExpress20.327s (~)21.059s (~)0.732s21.92x
🐘 PostgresNitro20.388s (+32.0% 🔺)21.054s (+31.2% 🔺)0.666s21.92x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express17.270s (+0.9%)18.449s (+3.7%)1.179s21.00x
▲ VercelNext.js (Turbopack)17.501s (-2.8%)18.877s (-1.6%)1.376s21.01x
▲ VercelNitro18.538s (+5.0% 🔺)19.543s (+5.2% 🔺)1.005s21.07x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)26.563s27.051s0.488s31.00x
💻 LocalNext.js (Turbopack)27.133s28.048s0.915s31.02x
💻 LocalExpress27.473s (~)28.050s (~)0.577s31.03x
💻 LocalNitro27.607s (~)28.053s (~)0.446s31.04x
🌐 MongoDBNext.js (Turbopack)30.649s31.045s0.396s21.15x
🐘 PostgresNext.js (Turbopack)37.630s38.089s0.459s21.42x
🐘 PostgresNitro50.155s (+32.8% 🔺)50.622s (+32.9% 🔺)0.467s21.89x
🐘 PostgresExpress50.347s (~)51.133s (~)0.785s21.90x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express43.009s (-4.6%)45.845s (-2.6%)2.836s21.00x
▲ VercelNext.js (Turbopack)43.117s (-4.7%)44.092s (-4.4%)0.974s21.00x
▲ VercelNitro43.536s (+3.7%)45.021s (+3.7%)1.485s21.01x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)53.737s54.099s0.362s21.00x
💻 LocalNext.js (Turbopack)56.586s57.096s0.511s21.05x
💻 LocalExpress57.392s (~)58.101s (~)0.709s21.07x
💻 LocalNitro57.471s (~)58.104s (~)0.632s21.07x
🌐 MongoDBNext.js (Turbopack)61.136s61.582s0.446s21.14x
🐘 PostgresExpress75.430s (-24.7% 🟢)76.181s (-24.0% 🟢)0.750s21.40x
🐘 PostgresNext.js (Turbopack)75.573s76.172s0.599s21.41x
🐘 PostgresNitro77.254s (+2.4%)77.669s (+1.9%)0.415s21.44x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro86.156s (~)87.467s (~)1.311s21.00x
▲ VercelNext.js (Turbopack)87.287s (-1.0%)88.401s (-1.0%)1.113s21.01x
▲ VercelExpress92.167s (+6.0% 🔺)92.965s (+5.8% 🔺)0.798s11.07x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.209s2.006s0.797s151.00x
💻 LocalNext.js (Turbopack)1.377s2.004s0.627s151.14x
💻 LocalNitro1.406s (-2.3%)2.006s (~)0.599s151.16x
💻 LocalExpress1.412s (~)2.005s (~)0.593s151.17x
🐘 PostgresNext.js (Turbopack)1.929s2.226s0.297s141.59x
🐘 PostgresExpress2.002s (-11.5% 🟢)2.682s (-11.0% 🟢)0.681s121.66x
🌐 MongoDBNext.js (Turbopack)2.158s3.008s0.851s101.78x
🐘 PostgresNitro2.276s (+6.7% 🔺)3.015s (+10.0% 🔺)0.738s101.88x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.395s (-0.7%)3.370s (-3.1%)0.974s91.00x
▲ VercelNitro2.424s (-1.3%)3.783s (+7.5% 🔺)1.359s81.01x
▲ VercelNext.js (Turbopack)2.836s (+11.2% 🔺)3.768s (-1.6%)0.932s81.18x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.403s3.008s0.605s101.00x
💻 LocalNitro2.526s (-3.2%)3.008s (~)0.481s101.05x
💻 LocalNext.js (Turbopack)2.541s3.007s0.466s101.06x
💻 LocalExpress2.581s (-1.1%)3.006s (~)0.425s101.07x
🌐 MongoDBNext.js (Turbopack)4.693s5.178s0.485s61.95x
🐘 PostgresNitro6.872s (-35.7% 🟢)7.226s (-34.5% 🟢)0.354s52.86x
🐘 PostgresExpress10.043s (+7.1% 🔺)10.367s (+8.7% 🔺)0.323s34.18x
🐘 PostgresNext.js (Turbopack)10.800s11.367s0.567s34.49x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.567s (-12.0% 🟢)3.862s (-3.6%)1.295s81.00x
▲ VercelNext.js (Turbopack)2.701s (-21.9% 🟢)4.004s (-14.7% 🟢)1.304s81.05x
▲ VercelExpress3.794s (+21.5% 🔺)5.064s (+25.7% 🔺)1.271s61.48x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.929s4.135s0.206s81.00x
💻 LocalNitro7.258s (-3.1%)8.019s (~)0.762s41.85x
💻 LocalExpress7.423s (-1.3%)8.016s (~)0.593s41.89x
💻 LocalNext.js (Turbopack)7.486s7.769s0.282s41.91x
🌐 MongoDBNext.js (Turbopack)9.727s10.352s0.625s32.48x
🐘 PostgresExpress47.361s (-2.2%)48.107s (-2.1%)0.746s112.05x
🐘 PostgresNitro48.096s (-5.7% 🟢)48.117s (-5.9% 🟢)0.021s112.24x
🐘 PostgresNext.js (Turbopack)49.877s50.116s0.239s112.70x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.192s (~)4.148s (-10.5% 🟢)0.955s81.00x
▲ VercelExpress3.249s (-26.1% 🟢)4.185s (-32.5% 🟢)0.935s81.02x
▲ VercelNext.js (Turbopack)3.799s (-58.3% 🟢)5.156s (-48.1% 🟢)1.357s61.19x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.210s2.006s0.796s151.00x
💻 LocalExpress1.417s (-1.1%)2.006s (~)0.588s151.17x
💻 LocalNext.js (Turbopack)1.427s2.005s0.578s151.18x
💻 LocalNitro1.461s (+2.2%)2.006s (~)0.545s151.21x
🐘 PostgresNitro1.920s (-15.4% 🟢)2.078s (-20.0% 🟢)0.158s151.59x
🐘 PostgresNext.js (Turbopack)2.071s2.596s0.525s121.71x
🐘 PostgresExpress2.108s (-0.9%)2.475s (-15.3% 🟢)0.367s131.74x
🌐 MongoDBNext.js (Turbopack)2.156s3.008s0.853s101.78x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.127s (-74.5% 🟢)3.048s (-68.8% 🟢)0.920s101.00x
▲ VercelNitro2.218s (-69.7% 🟢)3.447s (-59.4% 🟢)1.229s91.04x
▲ VercelNext.js (Turbopack)2.425s (-8.7% 🟢)3.632s (-4.4%)1.207s91.14x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.360s3.008s0.648s101.00x
💻 LocalNext.js (Turbopack)2.599s3.008s0.409s101.10x
💻 LocalNitro2.670s (-1.1%)3.008s (~)0.338s101.13x
💻 LocalExpress2.689s (~)3.008s (~)0.319s101.14x
🌐 MongoDBNext.js (Turbopack)4.703s5.177s0.474s61.99x
🐘 PostgresNitro11.509s (+6.1% 🔺)12.370s (+5.7% 🔺)0.861s34.88x
🐘 PostgresNext.js (Turbopack)11.704s12.364s0.660s34.96x
🐘 PostgresExpress12.371s (+5.2% 🔺)12.702s (+2.7%)0.331s35.24x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.341s (-13.1% 🟢)3.165s (-22.6% 🟢)0.823s101.00x
▲ VercelNitro2.689s (~)4.346s (+19.2% 🔺)1.657s71.15x
▲ VercelNext.js (Turbopack)2.839s (-0.9%)3.983s (+4.1%)1.144s91.21x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.889s4.260s0.371s81.00x
💻 LocalNitro7.545s (-6.3% 🟢)8.020s (-5.9% 🟢)0.476s41.94x
💻 LocalNext.js (Turbopack)7.895s8.267s0.372s42.03x
💻 LocalExpress8.148s (+3.1%)9.024s (+2.9%)0.876s42.10x
🌐 MongoDBNext.js (Turbopack)9.732s10.351s0.619s32.50x
🐘 PostgresExpress49.140s (-3.9%)50.108s (-3.9%)0.968s112.64x
🐘 PostgresNitro53.097s (+1.9%)53.121s (~)0.024s113.65x
🐘 PostgresNext.js (Turbopack)56.257s57.116s0.859s114.47x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.627s (-24.6% 🟢)3.580s (-19.0% 🟢)0.953s91.00x
▲ VercelNext.js (Turbopack)3.118s (-31.2% 🟢)4.557s (-17.8% 🟢)1.439s71.19x
▲ VercelNitro4.048s (+34.3% 🔺)5.250s (+32.1% 🔺)1.202s61.54x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)0.110s1.000s0.001s1.007s0.896s101.00x
💻 LocalNext.js (Turbopack)0.140s1.001s0.011s1.016s0.876s101.27x
💻 LocalExpress0.173s (~)1.002s (~)0.011s (+7.5% 🔺)1.017s (~)0.844s101.57x
💻 LocalNitro0.188s (+0.6%)1.002s (~)0.010s (-15.8% 🟢)1.016s (~)0.828s101.71x
🌐 MongoDBNext.js (Turbopack)0.500s0.949s0.001s1.009s0.509s104.53x
🐘 PostgresExpress1.291s (-44.9% 🟢)1.831s (-32.2% 🟢)0.002s (+25.0% 🔺)2.013s (-33.2% 🟢)0.722s1011.70x
🐘 PostgresNext.js (Turbopack)1.391s1.655s0.001s2.013s0.622s1012.61x
🐘 PostgresNitro1.413s (+16.4% 🔺)1.694s (-7.1% 🟢)0.002s (+7.1% 🔺)2.012s (~)0.600s1012.81x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.016s (+3.0%)2.886s (+3.6%)0.164s (-66.7% 🟢)3.607s (-5.7% 🟢)1.591s101.00x
▲ VercelNitro2.051s (+7.7% 🔺)2.772s (-19.8% 🟢)0.545s (+310.7% 🔺)3.939s (-4.5%)1.888s101.02x
▲ VercelExpress2.080s (+5.0% 🔺)2.771s (~)0.660s (+212.5% 🔺)3.916s (+10.5% 🔺)1.836s101.03x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)7/12
🐘 PostgresNitro4/12
▲ VercelExpress8/12
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express💻 Local9/12
Next.js (Turbopack)🌐 Redis10/12
Nitro💻 Local10/12
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TooTallNate@pranaygp@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix projectConfig.projectId containing project name instead of ID - #999

Merged
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config
Feb 18, 2026
Merged

Fix projectConfig.projectId containing project name instead of ID#999
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Feb 11, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes WORKFLOW_VERCEL_PROJECT env var to contain the real project ID instead of the project name/slug
  • Adds WORKFLOW_VERCEL_PROJECT_NAME for the project slug

@github-actions

github-actionsBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production534038572
✅ 💻 Local Development556068624
✅ 📦 Local Production556068624
✅ 🐘 Local Postgres556068624
✅ 🪟 Windows490352
❌ 🌍 Community Worlds111459165
✅ 📋 Other135021156
Total2497452752817

❌ Failed Tests

🌍 Community Worlds (45 failed)

turso (45 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • parallelSleepWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling retry behavior workflow completes despite transient 5xx on step_completed
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument
  • cancelRun - cancelling a running workflow
  • cancelRun via CLI - cancelling a running workflow
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro4804
✅ example4804
✅ express4804
✅ fastify4804
✅ hono4804
✅ nextjs-turbopack5101
✅ nextjs-webpack5101
✅ nitro4804
✅ nuxt4804
✅ sveltekit4804
✅ vite4804
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack4903
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev300
✅ mongodb4903
✅ redis-dev300
✅ redis4903
✅ turso-dev300
❌ turso4453
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable4507
✅ e2e-local-postgres-nest-stable4507
✅ e2e-local-prod-nest-stable4507

📋 View full workflow run

@changeset-bot

changeset-botBot commented Feb 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2a6cf4b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
@workflow/world-vercelPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/web-sharedPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNate marked this pull request as ready for review February 11, 2026 04:18
CopilotAI review requested due to automatic review settings February 11, 2026 04:18

@vercelvercelBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

Connection status UI displays opaque Vercel project ID (e.g., prj_xxx) instead of the human-readable project name after WORKFLOW_VERCEL_PROJECT was changed to store the real project ID.

Fix on Vercel

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes inconsistent handling of Vercel project identity by separating the project ID (used for API/auth/encryption contexts) from the project slug/name (used for dashboard URLs and display), and wires the new env var through CLI, core runtime, and the web server’s Vercel world creation path.

Changes:

  • Added WORKFLOW_VERCEL_PROJECT_NAME (project slug/name) alongside WORKFLOW_VERCEL_PROJECT (real prj_… id).
  • Updated CLI env inference to set WORKFLOW_VERCEL_PROJECT to the true project ID and populate the new project-name env var.
  • Plumbed projectName through core/runtime world creation and web server env allowlists / Vercel world instantiation.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
packages/world-vercel/src/utils.tsExtends Vercel world config typing to include both project ID and project slug/name.
packages/web/src/server/workflow-server-actions.tsAllows the new env var to reach the client and passes it into createVercelWorld().
packages/core/src/runtime/world.tsAdds WORKFLOW_VERCEL_PROJECT_NAME into the runtime’s Vercel world config.
packages/cli/src/lib/inspect/web.tsUses project slug/name (when available) for dashboard URL generation.
packages/cli/src/lib/inspect/env.tsAdds the new env var and updates Vercel env inference to distinguish ID vs name.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 203 to +207
'WORKFLOW_TARGET_WORLD',
'WORKFLOW_VERCEL_ENV',
'WORKFLOW_VERCEL_TEAM',
'WORKFLOW_VERCEL_PROJECT',
'WORKFLOW_VERCEL_PROJECT_NAME',

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says the web UI was updated to prefer the Vercel project name/slug when available, but the only consumer updated here appears to be the CLI dashboard URL logic. The web UI still appears to read/display WORKFLOW_VERCEL_PROJECT (now intended to be the prj_… id), so the UI may show IDs instead of friendly slugs unless the client-side components are updated to use WORKFLOW_VERCEL_PROJECT_NAME.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web UI path changed significantly during the React Router refactor. The web server actions now use createVercelWorld() which receives projectConfig with both projectId and projectName. The dashboard URL logic uses the name/slug.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web server actions use createVercelWorld() which receives both projectId and projectName via projectConfig. The dashboard URL uses the name/slug. No additional web UI changes needed.

Comment on lines +193 to +196
// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inferVercelEnvVars() only populates WORKFLOW_VERCEL_PROJECT_NAME (and normalizes WORKFLOW_VERCEL_PROJECT to a real prj_… id) when either WORKFLOW_VERCEL_PROJECT or WORKFLOW_VERCEL_TEAM is missing. If the CLI flag/env already sets WORKFLOW_VERCEL_PROJECT to a project slug/name (which the --project flag description currently implies), this block won’t run, and the world will continue sending the slug in the x-vercel-project-id header—reintroducing the exact bug this PR is fixing and potentially breaking auth/encryption context. Consider expanding the guard to also run when WORKFLOW_VERCEL_PROJECT_NAME is missing and/or when WORKFLOW_VERCEL_PROJECT doesn’t look like a Vercel project id (e.g. not prj_…), so the env vars are consistently normalized.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inference logic normalizes the env var to a real project ID when the linked project is available. If the user sets WORKFLOW_VERCEL_PROJECT to a slug, the inference step replaces it with the real ID from .vercel/project.json.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the guard now also runs when WORKFLOW_VERCEL_PROJECT does not start with prj_ or when WORKFLOW_VERCEL_PROJECT_NAME is missing, ensuring consistent normalization regardless of how the env vars were initially populated.

@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from a4be5e8 to 53d573eCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/encryptor-interface branch from 30fc9e5 to fc25b9cCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from 2746c5a to c6af179CompareFebruary 16, 2026 07:56

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but comment is changelog is off

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems off. The actual code doesn't change projectId at all. It seems more like:

Suggested change
Fix `projectConfig.projectId` to contain the real project ID instead of the project name
In UI, show project name instead in ID when available

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's not a UI change. In the world-vercel projectConfig, the projectId was previously being set to the project slug, not the ID.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the changeset description to: "Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)"

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is a clean and well-scoped fix. The separation of project ID vs project name/slug is the right approach. Two items to address:

  1. Connection status UI regression: packages/web/app/components/display-utils/connection-status.tsx:33 reads publicEnv.WORKFLOW_VERCEL_PROJECT to display the connection info string (e.g. team/project). Since WORKFLOW_VERCEL_PROJECT now contains the opaque prj_xxx ID, this will show IDs instead of friendly names. Should be updated to prefer WORKFLOW_VERCEL_PROJECT_NAME, same pattern as packages/cli/src/lib/inspect/web.ts:101-102:
constproject=publicEnv.WORKFLOW_VERCEL_PROJECT_NAME||publicEnv.WORKFLOW_VERCEL_PROJECT;

The Vercel bot flagged this as well.

  1. Changeset description is misleading (see inline comment).

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @VaguelySerious — the changeset description is misleading. The PR doesn't change what projectConfig.projectId contains (it was always the real project ID from .vercel/project.json). The actual fix is that WORKFLOW_VERCEL_PROJECT env var now correctly stores the real project ID instead of the project name/slug, and a new WORKFLOW_VERCEL_PROJECT_NAME env var is introduced for the slug.

Suggested:

Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — used your suggested wording.

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a broader pass across the codebase for project ID/name consistency. A few more things beyond my earlier review:

Naming inconsistency: WORKFLOW_VERCEL_PROJECT_SLUG vs WORKFLOW_VERCEL_PROJECT_NAME

CI already defines a third env var — WORKFLOW_VERCEL_PROJECT_SLUG — used in tests.yml:268, benchmarks.yml:397, and consumed by e2e tests (packages/core/e2e/e2e.test.ts:62) and benchmarks (packages/core/e2e/bench.bench.ts:156). This PR introduces WORKFLOW_VERCEL_PROJECT_NAME for the same concept. That's now two env vars for the project slug/name. Worth unifying on one name (probably WORKFLOW_VERCEL_PROJECT_NAME since it's the new standard) and updating CI + e2e tests to match, or at minimum documenting the relationship.

--project CLI flag can accept a slug

In packages/cli/src/lib/inspect/flags.ts:52-61, the --project flag maps directly to WORKFLOW_VERCEL_PROJECT. Its description says "the vercel project to authenticate against" — users could reasonably pass a slug here. In setup.ts:78, this value is written straight to WORKFLOW_VERCEL_PROJECTbeforeinferVercelEnvVars() runs. Since inferVercelEnvVars() only triggers when WORKFLOW_VERCEL_PROJECT is empty (line 188), a user-provided slug would persist as the "project ID" and get sent in the x-vercel-project-id header — reintroducing the original bug. This is the same concern Copilot raised. Consider either:

  • Normalizing in inferVercelEnvVars even when the env var is already set (e.g., if it doesn't start with prj_)
  • Or splitting the flag into --project-id and --project-name

projectName is carried but never consumed in world-vercel

The APIConfig.projectConfig.projectName field was added to the type in packages/world-vercel/src/utils.ts:40, but getHeaders() (line 173) and getHttpUrl() (line 155) never read it — only projectId and teamId are used for headers and proxy routing. This is fine since it's only for display, but a doc note clarifying it's not sent to the server would help future readers.

// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard on line 188 (!envVars.WORKFLOW_VERCEL_PROJECT || !envVars.WORKFLOW_VERCEL_TEAM) means inference is skipped entirely when both are already set. But WORKFLOW_VERCEL_PROJECT could contain a slug from the --project CLI flag (see flags.ts:58 and setup.ts:78), and WORKFLOW_VERCEL_PROJECT_NAME would remain empty.

Consider also running normalization when WORKFLOW_VERCEL_PROJECT is set but doesn't look like a real project ID (e.g., doesn't start with prj_), or when WORKFLOW_VERCEL_PROJECT_NAME is missing. This would make the env vars robust regardless of how they were initially populated.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Expanded the guard to also run inference when:

  • WORKFLOW_VERCEL_PROJECT does not start with prj_ (e.g., slug from --project flag)
  • WORKFLOW_VERCEL_PROJECT_NAME is missing

Also changed the team assignment to preserve an explicitly set team (envVars.WORKFLOW_VERCEL_TEAM || teamId) so only missing values get populated during normalization.

Comment threadpackages/core/src/runtime/world.ts Outdated
projectConfig: {
environment: process.env.WORKFLOW_VERCEL_ENV,
projectId: process.env.WORKFLOW_VERCEL_PROJECT,
projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could add a brief comment here (like in env.ts) clarifying the distinction:

projectId: process.env.WORKFLOW_VERCEL_PROJECT,// real ID (prj_xxx)projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,// slug (my-app)

Helps future readers understand the split without needing to trace back to the CLI.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added inline comments clarifying the distinction.

@github-actions

github-actionsBot commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.032s (+1.6%)1.005s (~)0.973s101.00x
💻 LocalNitro0.034s (+1.2%)1.005s (~)0.971s101.05x
🌐 RedisNext.js (Turbopack)0.038s1.005s0.967s101.18x
💻 LocalNext.js (Turbopack)0.043s1.004s0.961s101.33x
🌐 MongoDBNext.js (Turbopack)0.100s1.007s0.907s103.10x
🐘 PostgresNitro0.106s (-45.6% 🟢)1.010s (~)0.904s103.26x
🐘 PostgresExpress0.134s (-71.5% 🟢)1.010s (-0.5%)0.876s104.14x
🐘 PostgresNext.js (Turbopack)0.453s1.009s0.557s1013.97x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.513s (-13.6% 🟢)1.784s (-21.4% 🟢)1.271s101.00x
▲ VercelNitro0.684s (-1.0%)2.144s (+2.6%)1.460s101.33x
▲ VercelNext.js (Turbopack)0.979s (+34.7% 🔺)2.389s (+2.1%)1.410s101.91x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.089s2.006s0.918s101.00x
💻 LocalNext.js (Turbopack)1.095s2.005s0.910s101.01x
💻 LocalExpress1.105s (~)2.006s (~)0.900s101.02x
💻 LocalNitro1.112s (~)2.005s (~)0.893s101.02x
🌐 MongoDBNext.js (Turbopack)1.309s2.009s0.700s101.20x
🐘 PostgresNext.js (Turbopack)1.841s2.011s0.171s101.69x
🐘 PostgresExpress2.456s (+3.2%)3.014s (~)0.558s102.26x
🐘 PostgresNitro2.495s (+18.5% 🔺)3.013s (+3.4%)0.518s102.29x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.226s (-2.3%)3.401s (-4.2%)1.175s101.00x
▲ VercelNext.js (Turbopack)2.332s (+5.3% 🔺)3.767s (+7.6% 🔺)1.435s101.05x
▲ VercelNitro2.802s (+22.8% 🔺)4.038s (+28.6% 🔺)1.236s101.26x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)10.594s11.022s0.429s31.00x
💻 LocalNext.js (Turbopack)10.697s11.020s0.323s31.01x
💻 LocalExpress10.819s (~)11.023s (~)0.203s31.02x
💻 LocalNitro10.887s (~)11.024s (~)0.137s31.03x
🌐 MongoDBNext.js (Turbopack)12.341s13.022s0.680s31.16x
🐘 PostgresNext.js (Turbopack)15.273s16.043s0.771s21.44x
🐘 PostgresExpress20.327s (~)21.059s (~)0.732s21.92x
🐘 PostgresNitro20.388s (+32.0% 🔺)21.054s (+31.2% 🔺)0.666s21.92x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express17.270s (+0.9%)18.449s (+3.7%)1.179s21.00x
▲ VercelNext.js (Turbopack)17.501s (-2.8%)18.877s (-1.6%)1.376s21.01x
▲ VercelNitro18.538s (+5.0% 🔺)19.543s (+5.2% 🔺)1.005s21.07x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)26.563s27.051s0.488s31.00x
💻 LocalNext.js (Turbopack)27.133s28.048s0.915s31.02x
💻 LocalExpress27.473s (~)28.050s (~)0.577s31.03x
💻 LocalNitro27.607s (~)28.053s (~)0.446s31.04x
🌐 MongoDBNext.js (Turbopack)30.649s31.045s0.396s21.15x
🐘 PostgresNext.js (Turbopack)37.630s38.089s0.459s21.42x
🐘 PostgresNitro50.155s (+32.8% 🔺)50.622s (+32.9% 🔺)0.467s21.89x
🐘 PostgresExpress50.347s (~)51.133s (~)0.785s21.90x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express43.009s (-4.6%)45.845s (-2.6%)2.836s21.00x
▲ VercelNext.js (Turbopack)43.117s (-4.7%)44.092s (-4.4%)0.974s21.00x
▲ VercelNitro43.536s (+3.7%)45.021s (+3.7%)1.485s21.01x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)53.737s54.099s0.362s21.00x
💻 LocalNext.js (Turbopack)56.586s57.096s0.511s21.05x
💻 LocalExpress57.392s (~)58.101s (~)0.709s21.07x
💻 LocalNitro57.471s (~)58.104s (~)0.632s21.07x
🌐 MongoDBNext.js (Turbopack)61.136s61.582s0.446s21.14x
🐘 PostgresExpress75.430s (-24.7% 🟢)76.181s (-24.0% 🟢)0.750s21.40x
🐘 PostgresNext.js (Turbopack)75.573s76.172s0.599s21.41x
🐘 PostgresNitro77.254s (+2.4%)77.669s (+1.9%)0.415s21.44x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro86.156s (~)87.467s (~)1.311s21.00x
▲ VercelNext.js (Turbopack)87.287s (-1.0%)88.401s (-1.0%)1.113s21.01x
▲ VercelExpress92.167s (+6.0% 🔺)92.965s (+5.8% 🔺)0.798s11.07x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.209s2.006s0.797s151.00x
💻 LocalNext.js (Turbopack)1.377s2.004s0.627s151.14x
💻 LocalNitro1.406s (-2.3%)2.006s (~)0.599s151.16x
💻 LocalExpress1.412s (~)2.005s (~)0.593s151.17x
🐘 PostgresNext.js (Turbopack)1.929s2.226s0.297s141.59x
🐘 PostgresExpress2.002s (-11.5% 🟢)2.682s (-11.0% 🟢)0.681s121.66x
🌐 MongoDBNext.js (Turbopack)2.158s3.008s0.851s101.78x
🐘 PostgresNitro2.276s (+6.7% 🔺)3.015s (+10.0% 🔺)0.738s101.88x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.395s (-0.7%)3.370s (-3.1%)0.974s91.00x
▲ VercelNitro2.424s (-1.3%)3.783s (+7.5% 🔺)1.359s81.01x
▲ VercelNext.js (Turbopack)2.836s (+11.2% 🔺)3.768s (-1.6%)0.932s81.18x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.403s3.008s0.605s101.00x
💻 LocalNitro2.526s (-3.2%)3.008s (~)0.481s101.05x
💻 LocalNext.js (Turbopack)2.541s3.007s0.466s101.06x
💻 LocalExpress2.581s (-1.1%)3.006s (~)0.425s101.07x
🌐 MongoDBNext.js (Turbopack)4.693s5.178s0.485s61.95x
🐘 PostgresNitro6.872s (-35.7% 🟢)7.226s (-34.5% 🟢)0.354s52.86x
🐘 PostgresExpress10.043s (+7.1% 🔺)10.367s (+8.7% 🔺)0.323s34.18x
🐘 PostgresNext.js (Turbopack)10.800s11.367s0.567s34.49x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.567s (-12.0% 🟢)3.862s (-3.6%)1.295s81.00x
▲ VercelNext.js (Turbopack)2.701s (-21.9% 🟢)4.004s (-14.7% 🟢)1.304s81.05x
▲ VercelExpress3.794s (+21.5% 🔺)5.064s (+25.7% 🔺)1.271s61.48x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.929s4.135s0.206s81.00x
💻 LocalNitro7.258s (-3.1%)8.019s (~)0.762s41.85x
💻 LocalExpress7.423s (-1.3%)8.016s (~)0.593s41.89x
💻 LocalNext.js (Turbopack)7.486s7.769s0.282s41.91x
🌐 MongoDBNext.js (Turbopack)9.727s10.352s0.625s32.48x
🐘 PostgresExpress47.361s (-2.2%)48.107s (-2.1%)0.746s112.05x
🐘 PostgresNitro48.096s (-5.7% 🟢)48.117s (-5.9% 🟢)0.021s112.24x
🐘 PostgresNext.js (Turbopack)49.877s50.116s0.239s112.70x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.192s (~)4.148s (-10.5% 🟢)0.955s81.00x
▲ VercelExpress3.249s (-26.1% 🟢)4.185s (-32.5% 🟢)0.935s81.02x
▲ VercelNext.js (Turbopack)3.799s (-58.3% 🟢)5.156s (-48.1% 🟢)1.357s61.19x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.210s2.006s0.796s151.00x
💻 LocalExpress1.417s (-1.1%)2.006s (~)0.588s151.17x
💻 LocalNext.js (Turbopack)1.427s2.005s0.578s151.18x
💻 LocalNitro1.461s (+2.2%)2.006s (~)0.545s151.21x
🐘 PostgresNitro1.920s (-15.4% 🟢)2.078s (-20.0% 🟢)0.158s151.59x
🐘 PostgresNext.js (Turbopack)2.071s2.596s0.525s121.71x
🐘 PostgresExpress2.108s (-0.9%)2.475s (-15.3% 🟢)0.367s131.74x
🌐 MongoDBNext.js (Turbopack)2.156s3.008s0.853s101.78x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.127s (-74.5% 🟢)3.048s (-68.8% 🟢)0.920s101.00x
▲ VercelNitro2.218s (-69.7% 🟢)3.447s (-59.4% 🟢)1.229s91.04x
▲ VercelNext.js (Turbopack)2.425s (-8.7% 🟢)3.632s (-4.4%)1.207s91.14x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.360s3.008s0.648s101.00x
💻 LocalNext.js (Turbopack)2.599s3.008s0.409s101.10x
💻 LocalNitro2.670s (-1.1%)3.008s (~)0.338s101.13x
💻 LocalExpress2.689s (~)3.008s (~)0.319s101.14x
🌐 MongoDBNext.js (Turbopack)4.703s5.177s0.474s61.99x
🐘 PostgresNitro11.509s (+6.1% 🔺)12.370s (+5.7% 🔺)0.861s34.88x
🐘 PostgresNext.js (Turbopack)11.704s12.364s0.660s34.96x
🐘 PostgresExpress12.371s (+5.2% 🔺)12.702s (+2.7%)0.331s35.24x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.341s (-13.1% 🟢)3.165s (-22.6% 🟢)0.823s101.00x
▲ VercelNitro2.689s (~)4.346s (+19.2% 🔺)1.657s71.15x
▲ VercelNext.js (Turbopack)2.839s (-0.9%)3.983s (+4.1%)1.144s91.21x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.889s4.260s0.371s81.00x
💻 LocalNitro7.545s (-6.3% 🟢)8.020s (-5.9% 🟢)0.476s41.94x
💻 LocalNext.js (Turbopack)7.895s8.267s0.372s42.03x
💻 LocalExpress8.148s (+3.1%)9.024s (+2.9%)0.876s42.10x
🌐 MongoDBNext.js (Turbopack)9.732s10.351s0.619s32.50x
🐘 PostgresExpress49.140s (-3.9%)50.108s (-3.9%)0.968s112.64x
🐘 PostgresNitro53.097s (+1.9%)53.121s (~)0.024s113.65x
🐘 PostgresNext.js (Turbopack)56.257s57.116s0.859s114.47x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.627s (-24.6% 🟢)3.580s (-19.0% 🟢)0.953s91.00x
▲ VercelNext.js (Turbopack)3.118s (-31.2% 🟢)4.557s (-17.8% 🟢)1.439s71.19x
▲ VercelNitro4.048s (+34.3% 🔺)5.250s (+32.1% 🔺)1.202s61.54x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)0.110s1.000s0.001s1.007s0.896s101.00x
💻 LocalNext.js (Turbopack)0.140s1.001s0.011s1.016s0.876s101.27x
💻 LocalExpress0.173s (~)1.002s (~)0.011s (+7.5% 🔺)1.017s (~)0.844s101.57x
💻 LocalNitro0.188s (+0.6%)1.002s (~)0.010s (-15.8% 🟢)1.016s (~)0.828s101.71x
🌐 MongoDBNext.js (Turbopack)0.500s0.949s0.001s1.009s0.509s104.53x
🐘 PostgresExpress1.291s (-44.9% 🟢)1.831s (-32.2% 🟢)0.002s (+25.0% 🔺)2.013s (-33.2% 🟢)0.722s1011.70x
🐘 PostgresNext.js (Turbopack)1.391s1.655s0.001s2.013s0.622s1012.61x
🐘 PostgresNitro1.413s (+16.4% 🔺)1.694s (-7.1% 🟢)0.002s (+7.1% 🔺)2.012s (~)0.600s1012.81x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.016s (+3.0%)2.886s (+3.6%)0.164s (-66.7% 🟢)3.607s (-5.7% 🟢)1.591s101.00x
▲ VercelNitro2.051s (+7.7% 🔺)2.772s (-19.8% 🟢)0.545s (+310.7% 🔺)3.939s (-4.5%)1.888s101.02x
▲ VercelExpress2.080s (+5.0% 🔺)2.771s (~)0.660s (+212.5% 🔺)3.916s (+10.5% 🔺)1.836s101.03x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)7/12
🐘 PostgresNitro4/12
▲ VercelExpress8/12
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express💻 Local9/12
Next.js (Turbopack)🌐 Redis10/12
Nitro💻 Local10/12
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TooTallNate@pranaygp@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fix projectConfig.projectId containing project name instead of ID - #999

Merged
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config
Feb 18, 2026
Merged

Fix projectConfig.projectId containing project name instead of ID#999
TooTallNate merged 3 commits into
mainfrom
nate/fix-project-config

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Feb 11, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes WORKFLOW_VERCEL_PROJECT env var to contain the real project ID instead of the project name/slug
  • Adds WORKFLOW_VERCEL_PROJECT_NAME for the project slug

@github-actions

github-actionsBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production534038572
✅ 💻 Local Development556068624
✅ 📦 Local Production556068624
✅ 🐘 Local Postgres556068624
✅ 🪟 Windows490352
❌ 🌍 Community Worlds111459165
✅ 📋 Other135021156
Total2497452752817

❌ Failed Tests

🌍 Community Worlds (45 failed)

turso (45 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • parallelSleepWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling retry behavior workflow completes despite transient 5xx on step_completed
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument
  • cancelRun - cancelling a running workflow
  • cancelRun via CLI - cancelling a running workflow
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro4804
✅ example4804
✅ express4804
✅ fastify4804
✅ hono4804
✅ nextjs-turbopack5101
✅ nextjs-webpack5101
✅ nitro4804
✅ nuxt4804
✅ sveltekit4804
✅ vite4804
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable4507
✅ express-stable4507
✅ fastify-stable4507
✅ hono-stable4507
✅ nextjs-turbopack-canary4903
✅ nextjs-turbopack-stable4903
✅ nextjs-webpack-canary4903
✅ nextjs-webpack-stable4903
✅ nitro-stable4507
✅ nuxt-stable4507
✅ sveltekit-stable4507
✅ vite-stable4507
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack4903
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev300
✅ mongodb4903
✅ redis-dev300
✅ redis4903
✅ turso-dev300
❌ turso4453
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable4507
✅ e2e-local-postgres-nest-stable4507
✅ e2e-local-prod-nest-stable4507

📋 View full workflow run

@changeset-bot

changeset-botBot commented Feb 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2a6cf4b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/cliPatch
@workflow/corePatch
@workflow/webPatch
@workflow/world-vercelPatch
workflowPatch
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/web-sharedPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNate marked this pull request as ready for review February 11, 2026 04:18
CopilotAI review requested due to automatic review settings February 11, 2026 04:18

@vercelvercelBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

Connection status UI displays opaque Vercel project ID (e.g., prj_xxx) instead of the human-readable project name after WORKFLOW_VERCEL_PROJECT was changed to store the real project ID.

Fix on Vercel

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes inconsistent handling of Vercel project identity by separating the project ID (used for API/auth/encryption contexts) from the project slug/name (used for dashboard URLs and display), and wires the new env var through CLI, core runtime, and the web server’s Vercel world creation path.

Changes:

  • Added WORKFLOW_VERCEL_PROJECT_NAME (project slug/name) alongside WORKFLOW_VERCEL_PROJECT (real prj_… id).
  • Updated CLI env inference to set WORKFLOW_VERCEL_PROJECT to the true project ID and populate the new project-name env var.
  • Plumbed projectName through core/runtime world creation and web server env allowlists / Vercel world instantiation.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
packages/world-vercel/src/utils.tsExtends Vercel world config typing to include both project ID and project slug/name.
packages/web/src/server/workflow-server-actions.tsAllows the new env var to reach the client and passes it into createVercelWorld().
packages/core/src/runtime/world.tsAdds WORKFLOW_VERCEL_PROJECT_NAME into the runtime’s Vercel world config.
packages/cli/src/lib/inspect/web.tsUses project slug/name (when available) for dashboard URL generation.
packages/cli/src/lib/inspect/env.tsAdds the new env var and updates Vercel env inference to distinguish ID vs name.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 203 to +207
'WORKFLOW_TARGET_WORLD',
'WORKFLOW_VERCEL_ENV',
'WORKFLOW_VERCEL_TEAM',
'WORKFLOW_VERCEL_PROJECT',
'WORKFLOW_VERCEL_PROJECT_NAME',

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says the web UI was updated to prefer the Vercel project name/slug when available, but the only consumer updated here appears to be the CLI dashboard URL logic. The web UI still appears to read/display WORKFLOW_VERCEL_PROJECT (now intended to be the prj_… id), so the UI may show IDs instead of friendly slugs unless the client-side components are updated to use WORKFLOW_VERCEL_PROJECT_NAME.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web UI path changed significantly during the React Router refactor. The web server actions now use createVercelWorld() which receives projectConfig with both projectId and projectName. The dashboard URL logic uses the name/slug.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web server actions use createVercelWorld() which receives both projectId and projectName via projectConfig. The dashboard URL uses the name/slug. No additional web UI changes needed.

Comment on lines +193 to +196
// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inferVercelEnvVars() only populates WORKFLOW_VERCEL_PROJECT_NAME (and normalizes WORKFLOW_VERCEL_PROJECT to a real prj_… id) when either WORKFLOW_VERCEL_PROJECT or WORKFLOW_VERCEL_TEAM is missing. If the CLI flag/env already sets WORKFLOW_VERCEL_PROJECT to a project slug/name (which the --project flag description currently implies), this block won’t run, and the world will continue sending the slug in the x-vercel-project-id header—reintroducing the exact bug this PR is fixing and potentially breaking auth/encryption context. Consider expanding the guard to also run when WORKFLOW_VERCEL_PROJECT_NAME is missing and/or when WORKFLOW_VERCEL_PROJECT doesn’t look like a Vercel project id (e.g. not prj_…), so the env vars are consistently normalized.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inference logic normalizes the env var to a real project ID when the linked project is available. If the user sets WORKFLOW_VERCEL_PROJECT to a slug, the inference step replaces it with the real ID from .vercel/project.json.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the guard now also runs when WORKFLOW_VERCEL_PROJECT does not start with prj_ or when WORKFLOW_VERCEL_PROJECT_NAME is missing, ensuring consistent normalization regardless of how the env vars were initially populated.

@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from a4be5e8 to 53d573eCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/encryptor-interface branch from 30fc9e5 to fc25b9cCompareFebruary 11, 2026 05:23
@TooTallNate
TooTallNateforce-pushed the nate/fix-project-config branch from 2746c5a to c6af179CompareFebruary 16, 2026 07:56

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but comment is changelog is off

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems off. The actual code doesn't change projectId at all. It seems more like:

Suggested change
Fix `projectConfig.projectId` to contain the real project ID instead of the project name
In UI, show project name instead in ID when available

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's not a UI change. In the world-vercel projectConfig, the projectId was previously being set to the project slug, not the ID.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the changeset description to: "Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)"

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is a clean and well-scoped fix. The separation of project ID vs project name/slug is the right approach. Two items to address:

  1. Connection status UI regression: packages/web/app/components/display-utils/connection-status.tsx:33 reads publicEnv.WORKFLOW_VERCEL_PROJECT to display the connection info string (e.g. team/project). Since WORKFLOW_VERCEL_PROJECT now contains the opaque prj_xxx ID, this will show IDs instead of friendly names. Should be updated to prefer WORKFLOW_VERCEL_PROJECT_NAME, same pattern as packages/cli/src/lib/inspect/web.ts:101-102:
constproject=publicEnv.WORKFLOW_VERCEL_PROJECT_NAME||publicEnv.WORKFLOW_VERCEL_PROJECT;

The Vercel bot flagged this as well.

  1. Changeset description is misleading (see inline comment).

Comment thread.changeset/fix-project-config.md Outdated
"@workflow/world-vercel": patch
---

Fix `projectConfig.projectId` to contain the real project ID instead of the project name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @VaguelySerious — the changeset description is misleading. The PR doesn't change what projectConfig.projectId contains (it was always the real project ID from .vercel/project.json). The actual fix is that WORKFLOW_VERCEL_PROJECT env var now correctly stores the real project ID instead of the project name/slug, and a new WORKFLOW_VERCEL_PROJECT_NAME env var is introduced for the slug.

Suggested:

Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — used your suggested wording.

@pranaygppranaygp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a broader pass across the codebase for project ID/name consistency. A few more things beyond my earlier review:

Naming inconsistency: WORKFLOW_VERCEL_PROJECT_SLUG vs WORKFLOW_VERCEL_PROJECT_NAME

CI already defines a third env var — WORKFLOW_VERCEL_PROJECT_SLUG — used in tests.yml:268, benchmarks.yml:397, and consumed by e2e tests (packages/core/e2e/e2e.test.ts:62) and benchmarks (packages/core/e2e/bench.bench.ts:156). This PR introduces WORKFLOW_VERCEL_PROJECT_NAME for the same concept. That's now two env vars for the project slug/name. Worth unifying on one name (probably WORKFLOW_VERCEL_PROJECT_NAME since it's the new standard) and updating CI + e2e tests to match, or at minimum documenting the relationship.

--project CLI flag can accept a slug

In packages/cli/src/lib/inspect/flags.ts:52-61, the --project flag maps directly to WORKFLOW_VERCEL_PROJECT. Its description says "the vercel project to authenticate against" — users could reasonably pass a slug here. In setup.ts:78, this value is written straight to WORKFLOW_VERCEL_PROJECTbeforeinferVercelEnvVars() runs. Since inferVercelEnvVars() only triggers when WORKFLOW_VERCEL_PROJECT is empty (line 188), a user-provided slug would persist as the "project ID" and get sent in the x-vercel-project-id header — reintroducing the original bug. This is the same concern Copilot raised. Consider either:

  • Normalizing in inferVercelEnvVars even when the env var is already set (e.g., if it doesn't start with prj_)
  • Or splitting the flag into --project-id and --project-name

projectName is carried but never consumed in world-vercel

The APIConfig.projectConfig.projectName field was added to the type in packages/world-vercel/src/utils.ts:40, but getHeaders() (line 173) and getHttpUrl() (line 155) never read it — only projectId and teamId are used for headers and proxy routing. This is fine since it's only for display, but a doc note clarifying it's not sent to the server would help future readers.

// WORKFLOW_VERCEL_PROJECT is the real project ID (e.g., prj_xxx)
envVars.WORKFLOW_VERCEL_PROJECT = projectId;
// WORKFLOW_VERCEL_PROJECT_NAME is the project slug (e.g., my-app)
envVars.WORKFLOW_VERCEL_PROJECT_NAME = projectName || projectId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard on line 188 (!envVars.WORKFLOW_VERCEL_PROJECT || !envVars.WORKFLOW_VERCEL_TEAM) means inference is skipped entirely when both are already set. But WORKFLOW_VERCEL_PROJECT could contain a slug from the --project CLI flag (see flags.ts:58 and setup.ts:78), and WORKFLOW_VERCEL_PROJECT_NAME would remain empty.

Consider also running normalization when WORKFLOW_VERCEL_PROJECT is set but doesn't look like a real project ID (e.g., doesn't start with prj_), or when WORKFLOW_VERCEL_PROJECT_NAME is missing. This would make the env vars robust regardless of how they were initially populated.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Expanded the guard to also run inference when:

  • WORKFLOW_VERCEL_PROJECT does not start with prj_ (e.g., slug from --project flag)
  • WORKFLOW_VERCEL_PROJECT_NAME is missing

Also changed the team assignment to preserve an explicitly set team (envVars.WORKFLOW_VERCEL_TEAM || teamId) so only missing values get populated during normalization.

Comment threadpackages/core/src/runtime/world.ts Outdated
projectConfig: {
environment: process.env.WORKFLOW_VERCEL_ENV,
projectId: process.env.WORKFLOW_VERCEL_PROJECT,
projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could add a brief comment here (like in env.ts) clarifying the distinction:

projectId: process.env.WORKFLOW_VERCEL_PROJECT,// real ID (prj_xxx)projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME,// slug (my-app)

Helps future readers understand the split without needing to trace back to the CLI.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added inline comments clarifying the distinction.

@github-actions

github-actionsBot commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.032s (+1.6%)1.005s (~)0.973s101.00x
💻 LocalNitro0.034s (+1.2%)1.005s (~)0.971s101.05x
🌐 RedisNext.js (Turbopack)0.038s1.005s0.967s101.18x
💻 LocalNext.js (Turbopack)0.043s1.004s0.961s101.33x
🌐 MongoDBNext.js (Turbopack)0.100s1.007s0.907s103.10x
🐘 PostgresNitro0.106s (-45.6% 🟢)1.010s (~)0.904s103.26x
🐘 PostgresExpress0.134s (-71.5% 🟢)1.010s (-0.5%)0.876s104.14x
🐘 PostgresNext.js (Turbopack)0.453s1.009s0.557s1013.97x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express0.513s (-13.6% 🟢)1.784s (-21.4% 🟢)1.271s101.00x
▲ VercelNitro0.684s (-1.0%)2.144s (+2.6%)1.460s101.33x
▲ VercelNext.js (Turbopack)0.979s (+34.7% 🔺)2.389s (+2.1%)1.410s101.91x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.089s2.006s0.918s101.00x
💻 LocalNext.js (Turbopack)1.095s2.005s0.910s101.01x
💻 LocalExpress1.105s (~)2.006s (~)0.900s101.02x
💻 LocalNitro1.112s (~)2.005s (~)0.893s101.02x
🌐 MongoDBNext.js (Turbopack)1.309s2.009s0.700s101.20x
🐘 PostgresNext.js (Turbopack)1.841s2.011s0.171s101.69x
🐘 PostgresExpress2.456s (+3.2%)3.014s (~)0.558s102.26x
🐘 PostgresNitro2.495s (+18.5% 🔺)3.013s (+3.4%)0.518s102.29x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.226s (-2.3%)3.401s (-4.2%)1.175s101.00x
▲ VercelNext.js (Turbopack)2.332s (+5.3% 🔺)3.767s (+7.6% 🔺)1.435s101.05x
▲ VercelNitro2.802s (+22.8% 🔺)4.038s (+28.6% 🔺)1.236s101.26x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)10.594s11.022s0.429s31.00x
💻 LocalNext.js (Turbopack)10.697s11.020s0.323s31.01x
💻 LocalExpress10.819s (~)11.023s (~)0.203s31.02x
💻 LocalNitro10.887s (~)11.024s (~)0.137s31.03x
🌐 MongoDBNext.js (Turbopack)12.341s13.022s0.680s31.16x
🐘 PostgresNext.js (Turbopack)15.273s16.043s0.771s21.44x
🐘 PostgresExpress20.327s (~)21.059s (~)0.732s21.92x
🐘 PostgresNitro20.388s (+32.0% 🔺)21.054s (+31.2% 🔺)0.666s21.92x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express17.270s (+0.9%)18.449s (+3.7%)1.179s21.00x
▲ VercelNext.js (Turbopack)17.501s (-2.8%)18.877s (-1.6%)1.376s21.01x
▲ VercelNitro18.538s (+5.0% 🔺)19.543s (+5.2% 🔺)1.005s21.07x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)26.563s27.051s0.488s31.00x
💻 LocalNext.js (Turbopack)27.133s28.048s0.915s31.02x
💻 LocalExpress27.473s (~)28.050s (~)0.577s31.03x
💻 LocalNitro27.607s (~)28.053s (~)0.446s31.04x
🌐 MongoDBNext.js (Turbopack)30.649s31.045s0.396s21.15x
🐘 PostgresNext.js (Turbopack)37.630s38.089s0.459s21.42x
🐘 PostgresNitro50.155s (+32.8% 🔺)50.622s (+32.9% 🔺)0.467s21.89x
🐘 PostgresExpress50.347s (~)51.133s (~)0.785s21.90x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express43.009s (-4.6%)45.845s (-2.6%)2.836s21.00x
▲ VercelNext.js (Turbopack)43.117s (-4.7%)44.092s (-4.4%)0.974s21.00x
▲ VercelNitro43.536s (+3.7%)45.021s (+3.7%)1.485s21.01x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)53.737s54.099s0.362s21.00x
💻 LocalNext.js (Turbopack)56.586s57.096s0.511s21.05x
💻 LocalExpress57.392s (~)58.101s (~)0.709s21.07x
💻 LocalNitro57.471s (~)58.104s (~)0.632s21.07x
🌐 MongoDBNext.js (Turbopack)61.136s61.582s0.446s21.14x
🐘 PostgresExpress75.430s (-24.7% 🟢)76.181s (-24.0% 🟢)0.750s21.40x
🐘 PostgresNext.js (Turbopack)75.573s76.172s0.599s21.41x
🐘 PostgresNitro77.254s (+2.4%)77.669s (+1.9%)0.415s21.44x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro86.156s (~)87.467s (~)1.311s21.00x
▲ VercelNext.js (Turbopack)87.287s (-1.0%)88.401s (-1.0%)1.113s21.01x
▲ VercelExpress92.167s (+6.0% 🔺)92.965s (+5.8% 🔺)0.798s11.07x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.209s2.006s0.797s151.00x
💻 LocalNext.js (Turbopack)1.377s2.004s0.627s151.14x
💻 LocalNitro1.406s (-2.3%)2.006s (~)0.599s151.16x
💻 LocalExpress1.412s (~)2.005s (~)0.593s151.17x
🐘 PostgresNext.js (Turbopack)1.929s2.226s0.297s141.59x
🐘 PostgresExpress2.002s (-11.5% 🟢)2.682s (-11.0% 🟢)0.681s121.66x
🌐 MongoDBNext.js (Turbopack)2.158s3.008s0.851s101.78x
🐘 PostgresNitro2.276s (+6.7% 🔺)3.015s (+10.0% 🔺)0.738s101.88x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.395s (-0.7%)3.370s (-3.1%)0.974s91.00x
▲ VercelNitro2.424s (-1.3%)3.783s (+7.5% 🔺)1.359s81.01x
▲ VercelNext.js (Turbopack)2.836s (+11.2% 🔺)3.768s (-1.6%)0.932s81.18x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.403s3.008s0.605s101.00x
💻 LocalNitro2.526s (-3.2%)3.008s (~)0.481s101.05x
💻 LocalNext.js (Turbopack)2.541s3.007s0.466s101.06x
💻 LocalExpress2.581s (-1.1%)3.006s (~)0.425s101.07x
🌐 MongoDBNext.js (Turbopack)4.693s5.178s0.485s61.95x
🐘 PostgresNitro6.872s (-35.7% 🟢)7.226s (-34.5% 🟢)0.354s52.86x
🐘 PostgresExpress10.043s (+7.1% 🔺)10.367s (+8.7% 🔺)0.323s34.18x
🐘 PostgresNext.js (Turbopack)10.800s11.367s0.567s34.49x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.567s (-12.0% 🟢)3.862s (-3.6%)1.295s81.00x
▲ VercelNext.js (Turbopack)2.701s (-21.9% 🟢)4.004s (-14.7% 🟢)1.304s81.05x
▲ VercelExpress3.794s (+21.5% 🔺)5.064s (+25.7% 🔺)1.271s61.48x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.929s4.135s0.206s81.00x
💻 LocalNitro7.258s (-3.1%)8.019s (~)0.762s41.85x
💻 LocalExpress7.423s (-1.3%)8.016s (~)0.593s41.89x
💻 LocalNext.js (Turbopack)7.486s7.769s0.282s41.91x
🌐 MongoDBNext.js (Turbopack)9.727s10.352s0.625s32.48x
🐘 PostgresExpress47.361s (-2.2%)48.107s (-2.1%)0.746s112.05x
🐘 PostgresNitro48.096s (-5.7% 🟢)48.117s (-5.9% 🟢)0.021s112.24x
🐘 PostgresNext.js (Turbopack)49.877s50.116s0.239s112.70x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.192s (~)4.148s (-10.5% 🟢)0.955s81.00x
▲ VercelExpress3.249s (-26.1% 🟢)4.185s (-32.5% 🟢)0.935s81.02x
▲ VercelNext.js (Turbopack)3.799s (-58.3% 🟢)5.156s (-48.1% 🟢)1.357s61.19x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)1.210s2.006s0.796s151.00x
💻 LocalExpress1.417s (-1.1%)2.006s (~)0.588s151.17x
💻 LocalNext.js (Turbopack)1.427s2.005s0.578s151.18x
💻 LocalNitro1.461s (+2.2%)2.006s (~)0.545s151.21x
🐘 PostgresNitro1.920s (-15.4% 🟢)2.078s (-20.0% 🟢)0.158s151.59x
🐘 PostgresNext.js (Turbopack)2.071s2.596s0.525s121.71x
🐘 PostgresExpress2.108s (-0.9%)2.475s (-15.3% 🟢)0.367s131.74x
🌐 MongoDBNext.js (Turbopack)2.156s3.008s0.853s101.78x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.127s (-74.5% 🟢)3.048s (-68.8% 🟢)0.920s101.00x
▲ VercelNitro2.218s (-69.7% 🟢)3.447s (-59.4% 🟢)1.229s91.04x
▲ VercelNext.js (Turbopack)2.425s (-8.7% 🟢)3.632s (-4.4%)1.207s91.14x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)2.360s3.008s0.648s101.00x
💻 LocalNext.js (Turbopack)2.599s3.008s0.409s101.10x
💻 LocalNitro2.670s (-1.1%)3.008s (~)0.338s101.13x
💻 LocalExpress2.689s (~)3.008s (~)0.319s101.14x
🌐 MongoDBNext.js (Turbopack)4.703s5.177s0.474s61.99x
🐘 PostgresNitro11.509s (+6.1% 🔺)12.370s (+5.7% 🔺)0.861s34.88x
🐘 PostgresNext.js (Turbopack)11.704s12.364s0.660s34.96x
🐘 PostgresExpress12.371s (+5.2% 🔺)12.702s (+2.7%)0.331s35.24x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.341s (-13.1% 🟢)3.165s (-22.6% 🟢)0.823s101.00x
▲ VercelNitro2.689s (~)4.346s (+19.2% 🔺)1.657s71.15x
▲ VercelNext.js (Turbopack)2.839s (-0.9%)3.983s (+4.1%)1.144s91.21x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)3.889s4.260s0.371s81.00x
💻 LocalNitro7.545s (-6.3% 🟢)8.020s (-5.9% 🟢)0.476s41.94x
💻 LocalNext.js (Turbopack)7.895s8.267s0.372s42.03x
💻 LocalExpress8.148s (+3.1%)9.024s (+2.9%)0.876s42.10x
🌐 MongoDBNext.js (Turbopack)9.732s10.351s0.619s32.50x
🐘 PostgresExpress49.140s (-3.9%)50.108s (-3.9%)0.968s112.64x
🐘 PostgresNitro53.097s (+1.9%)53.121s (~)0.024s113.65x
🐘 PostgresNext.js (Turbopack)56.257s57.116s0.859s114.47x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.627s (-24.6% 🟢)3.580s (-19.0% 🟢)0.953s91.00x
▲ VercelNext.js (Turbopack)3.118s (-31.2% 🟢)4.557s (-17.8% 🟢)1.439s71.19x
▲ VercelNitro4.048s (+34.3% 🔺)5.250s (+32.1% 🔺)1.202s61.54x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🌐 Redis🥇 Next.js (Turbopack)0.110s1.000s0.001s1.007s0.896s101.00x
💻 LocalNext.js (Turbopack)0.140s1.001s0.011s1.016s0.876s101.27x
💻 LocalExpress0.173s (~)1.002s (~)0.011s (+7.5% 🔺)1.017s (~)0.844s101.57x
💻 LocalNitro0.188s (+0.6%)1.002s (~)0.010s (-15.8% 🟢)1.016s (~)0.828s101.71x
🌐 MongoDBNext.js (Turbopack)0.500s0.949s0.001s1.009s0.509s104.53x
🐘 PostgresExpress1.291s (-44.9% 🟢)1.831s (-32.2% 🟢)0.002s (+25.0% 🔺)2.013s (-33.2% 🟢)0.722s1011.70x
🐘 PostgresNext.js (Turbopack)1.391s1.655s0.001s2.013s0.622s1012.61x
🐘 PostgresNitro1.413s (+16.4% 🔺)1.694s (-7.1% 🟢)0.002s (+7.1% 🔺)2.012s (~)0.600s1012.81x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.016s (+3.0%)2.886s (+3.6%)0.164s (-66.7% 🟢)3.607s (-5.7% 🟢)1.591s101.00x
▲ VercelNitro2.051s (+7.7% 🔺)2.772s (-19.8% 🟢)0.545s (+310.7% 🔺)3.939s (-4.5%)1.888s101.02x
▲ VercelExpress2.080s (+5.0% 🔺)2.771s (~)0.660s (+212.5% 🔺)3.916s (+10.5% 🔺)1.836s101.03x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)7/12
🐘 PostgresNitro4/12
▲ VercelExpress8/12
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express💻 Local9/12
Next.js (Turbopack)🌐 Redis10/12
Nitro💻 Local10/12
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TooTallNate@pranaygp@VaguelySerious