Skip to content

Fix the production playground: embed the bundled assets - #8

Merged
SouravInsights merged 1 commit into
mainfrom
fix/playground-asset-tracing
Sep 18, 2026
Merged

SouravInsights merged 1 commit into
mainfrom
fix/playground-asset-tracing

Conversation

@SouravInsights

Copy link
Copy Markdown
Owner

The bug

Every production playground request failed:

webmcp-codegen: bundled asset missing: journey.webmcp.ts
(looked in /vercel/path0/packages/codegen/assets/journey.webmcp.ts,
 /vercel/path0/packages/assets/journey.webmcp.ts)

Generating tools always writes the journey helper and the agent skill, and assetText() read both from the package's assets/ directory with fs at runtime. Two things hid that until deploy:

  • webpack bundles the package into the route and rewrites import.meta.url to the build machine's absolute path. On a laptop that path exists, so the read succeeded from the developer's own checkout. On Vercel the same literal became /vercel/path0/....
  • Next's file tracer cannot see a readFile whose path is computed, so assets/ never entered the function bundle. The traced-files manifest for the route (.next/server/app/api/playground/route.js.nft.json) listed the package's package.json and nothing else.

So the failure was environment-shaped: fine locally, broken in every deployment.

The fix

The assets are embedded at package build time. assets.ts imports them as text (?raw), which vitest resolves natively and tsup resolves with a small esbuild plugin in the new packages/codegen/tsup.config.ts. The shipped code carries the text, so it never reads its own files at runtime and no host needs tracing configuration for them. assets/ stays the reviewed source of truth, and a new test asserts the embed matches it byte for byte.

Alternatives tried and rejected

  • outputFileTracingIncludes in site/next.config.mjs. Works, but it fixes this one host and leaves every other serverless use of the pipeline to rediscover the trap. The package now invites exactly that use by shipping runGenerate and dashboardState.
  • Static new URL("../assets/...", import.meta.url) references so tracers notice the files. Webpack rewrites those into web-served asset URLs (/_next/static/media/SKILL.<hash>.md), and readFile cannot open a web path. I caught this by deleting assets/ and running the production server, which still failed. That test is the reason the fix is embedding rather than tracing.

Verification

The deployment condition, reproduced locally: delete packages/codegen/assets, next build, next start, then POST specs.

Spec Before After
Petstore 422, "bundled asset missing" 200, 19 tools
Immich excerpt 422, "bundled asset missing" 200, 6 tools

Also checked:

  • The production bundle now carries the asset text inline (createJourney present) with zero static/media asset references and no baked file:/// build paths.
  • A real runGenerate into a scratch dir still writes journey.webmcp.ts and .agents/skills/webmcp-tools/SKILL.md byte-identical to assets/.
  • pnpm lint, pnpm typecheck, pnpm test, pnpm build all pass. Package tests 242, site tests 11.

After merge

Vercel redeploys main automatically, so the production playground should work without further changes. The changeset is a patch for @webmcp-stack/codegen, worth consuming in a release because the npm package had the same defect; the site itself needs no release, since it consumes the workspace package.

The hosted playground failed in production on every spec with "bundled asset
missing: journey.webmcp.ts". The tools output always writes the journey helper
and the agent skill, and assetText() read them from the package's assets/
directory with fs at runtime. That read is invisible twice over:

- webpack bundles the package into the route and rewrites import.meta.url to
the build machine's absolute path, so it succeeded locally from a developer's
own checkout
- Next's file tracer cannot see a readFile whose path is computed, so assets/
never entered the function bundle (the traced-files manifest listed the
package's package.json and nothing else)

The assets are now embedded at package build time: assets.ts imports them as
text (?raw), which vitest resolves natively and tsup resolves with a small
esbuild plugin. The shipped code carries the text, so no host has to be told
about these files. assets/ stays the reviewed source of truth and a test
asserts the embed matches it byte for byte.

A trace include in the site config would have fixed this one host and left
every other serverless use of the pipeline to rediscover the trap. Static
new URL references were tried first and rejected: webpack rewrites them into
web-served asset URLs that readFile cannot open.

Verified against the deployment condition: with packages/codegen/assets
deleted, next build plus next start generated 19 tools from the Petstore spec
and 6 from the Immich excerpt, both 200. Before, the same test returned 422
with the error above. A real generate run still writes the journey helper and
the skill byte-identical to assets/.
@vercel

vercel Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
webmcp-stack Ready Ready Preview Sep 18, 2026 11:13am UTC

@SouravInsights
SouravInsights merged commit acd1dff into main Sep 18, 2026
4 checks passed

This branch was successfully deployed

1 active deployment
Preview — 1c8e50fe Deployed Sep 18, 2026 by vercel[bot]
Sign up for free to 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.

1 participant