Fix projectConfig.projectId containing project name instead of ID#999
Fix projectConfig.projectId containing project name instead of ID#999TooTallNate merged 3 commits intomainfrom
Conversation
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests🌍 Community Worlds (45 failed)turso (45 failed):
Details by Category✅ ▲ Vercel Production
✅ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
❌ 🌍 Community Worlds
✅ 📋 Other
|
🦋 Changeset detectedLatest commit: 2a6cf4b The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
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 |
There was a problem hiding this comment.
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) alongsideWORKFLOW_VERCEL_PROJECT(realprj_…id). - Updated CLI env inference to set
WORKFLOW_VERCEL_PROJECTto the true project ID and populate the new project-name env var. - Plumbed
projectNamethrough 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
| File | Description |
|---|---|
| packages/world-vercel/src/utils.ts | Extends Vercel world config typing to include both project ID and project slug/name. |
| packages/web/src/server/workflow-server-actions.ts | Allows the new env var to reach the client and passes it into createVercelWorld(). |
| packages/core/src/runtime/world.ts | Adds WORKFLOW_VERCEL_PROJECT_NAME into the runtime’s Vercel world config. |
| packages/cli/src/lib/inspect/web.ts | Uses project slug/name (when available) for dashboard URL generation. |
| packages/cli/src/lib/inspect/env.ts | Adds 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.
| 'WORKFLOW_TARGET_WORLD', | ||
| 'WORKFLOW_VERCEL_ENV', | ||
| 'WORKFLOW_VERCEL_TEAM', | ||
| 'WORKFLOW_VERCEL_PROJECT', | ||
| 'WORKFLOW_VERCEL_PROJECT_NAME', |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
| // 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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
a4be5e8 to
53d573e
Compare
30fc9e5 to
fc25b9c
Compare
2746c5a to
c6af179
Compare
VaguelySerious
left a comment
There was a problem hiding this comment.
LGTM but comment is changelog is off
| "@workflow/world-vercel": patch | ||
| --- | ||
|
|
||
| Fix `projectConfig.projectId` to contain the real project ID instead of the project name |
There was a problem hiding this comment.
This seems off. The actual code doesn't change projectId at all. It seems more like:
| Fix `projectConfig.projectId` to contain the real project ID instead of the project name | |
| In UI, show project name instead in ID when available |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Updated the changeset description to: "Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)"
pranaygp
left a comment
There was a problem hiding this comment.
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:
- Connection status UI regression:
packages/web/app/components/display-utils/connection-status.tsx:33readspublicEnv.WORKFLOW_VERCEL_PROJECTto display the connection info string (e.g.team/project). SinceWORKFLOW_VERCEL_PROJECTnow contains the opaqueprj_xxxID, this will show IDs instead of friendly names. Should be updated to preferWORKFLOW_VERCEL_PROJECT_NAME, same pattern aspackages/cli/src/lib/inspect/web.ts:101-102:
const project = publicEnv.WORKFLOW_VERCEL_PROJECT_NAME || publicEnv.WORKFLOW_VERCEL_PROJECT;The Vercel bot flagged this as well.
- Changeset description is misleading (see inline comment).
| "@workflow/world-vercel": patch | ||
| --- | ||
|
|
||
| Fix `projectConfig.projectId` to contain the real project ID instead of the project name |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
Agreed — used your suggested wording.
pranaygp
left a comment
There was a problem hiding this comment.
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_PROJECT before inferVercelEnvVars() 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
inferVercelEnvVarseven when the env var is already set (e.g., if it doesn't start withprj_) - Or splitting the flag into
--project-idand--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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Good catch. Expanded the guard to also run inference when:
WORKFLOW_VERCEL_PROJECTdoes not start withprj_(e.g., slug from--projectflag)WORKFLOW_VERCEL_PROJECT_NAMEis 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.
| projectConfig: { | ||
| environment: process.env.WORKFLOW_VERCEL_ENV, | ||
| projectId: process.env.WORKFLOW_VERCEL_PROJECT, | ||
| projectName: process.env.WORKFLOW_VERCEL_PROJECT_NAME, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Added inline comments clarifying the distinction.
📊 Benchmark Results
workflow with no steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) workflow with 1 step💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) | Nitro workflow with 10 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) | Nitro workflow with 25 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) | Nitro workflow with 50 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Next.js (Turbopack) | Express Promise.all with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) Promise.all with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Next.js (Turbopack) | Express Promise.all with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) Promise.race with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) Promise.race with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) Promise.race with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) | Nitro Stream Benchmarks (includes TTFB metrics)workflow with stream💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Nitro | Express SummaryFastest Framework by WorldWinner determined by most benchmark wins
Fastest World by FrameworkWinner determined by most benchmark wins
Column Definitions
Worlds:
|
…ct IDs, add clarifying comments

Summary
WORKFLOW_VERCEL_PROJECTenv var to contain the real project ID instead of the project name/slugWORKFLOW_VERCEL_PROJECT_NAMEfor the project slug