New and improved manifest.json format#902
Conversation
🦋 Changeset detectedLatest commit: e5b5cff The changes in this PR will be included in the next version bump. This PR includes changesets to release 17 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 |
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests🌍 Community Worlds (169 failed)mongodb (42 failed):
redis (42 failed):
starter (43 failed):
turso (42 failed):
Details by Category✅ ▲ Vercel Production
✅ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
❌ 🌍 Community Worlds
✅ 📋 Other
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
There was a problem hiding this comment.
Pull request overview
This PR refactors the manifest.json format from a file-path-keyed structure to an ID-keyed structure, making manifest entries directly usable with APIs like start() and enabling O(1) lookups by ID.
Changes:
- Rust SWC plugin now emits ID-keyed manifest format with
nameandsourcefields - TypeScript builders convert raw manifests (with
source) to final manifests (withexportskeyed by condition) - New
mergeManifestsutility provides deep merging of exports from multiple bundle contexts - All test fixtures, integration tests, and documentation updated to reflect the new format
Reviewed changes
Copilot reviewed 148 out of 148 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/swc-plugin-workflow/transform/src/lib.rs | Rust transform updated to emit ID-keyed format with name/source fields |
| packages/builders/src/apply-swc-transform.ts | Added RawWorkflowManifest and updated WorkflowManifest types for new format |
| packages/builders/src/manifest-utils.ts | New file with deepMergeManifestEntries and mergeManifests utilities |
| packages/builders/src/base-builder.ts | Updated mergeRawManifest and addGraphsToWorkflows for new format |
| packages/builders/src/swc-esbuild-plugin.ts | Added mergeRawManifest function to convert raw to final manifest |
| packages/sveltekit/src/builder.ts | Updated to use new mergeManifests utility |
| packages/nitro/src/builders.ts | Updated to use new mergeManifests utility |
| packages/next/src/builder.ts | Updated to use new mergeManifests utility |
| packages/nest/src/builder.ts | Updated to use new mergeManifests utility |
| packages/builders/src/standalone.ts | Removed local mergeManifests in favor of shared utility |
| packages/builders/src/vercel-build-output-api.ts | Updated to use new mergeManifests utility |
| packages/builders/src/index.ts | Exported new mergeManifests utilities |
| packages/core/e2e/manifest.test.ts | Updated tests for ID-keyed manifest structure |
| workbench/example/api/trigger.ts | Updated to look up workflows by ID with backwards compatibility |
| packages/world-testing/src/*.mts | Updated to use ID-keyed manifest for workflow invocation |
| packages/swc-plugin-workflow/spec.md | Comprehensive documentation update explaining new format |
| All test fixture files | Updated expected output for new manifest format |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
3068a69 to
ef5febf
Compare
6cce073 to
ca8bd01
Compare
6b5c84a to
67fe853
Compare
pranaygp
left a comment
There was a problem hiding this comment.
Code Review Summary
The core changes are solid and well-implemented. The transformation from file-path-keyed to ID-keyed manifest format is correctly implemented across all packages with good test coverage and excellent documentation.
Highlights
- Well-documented PR description with clear migration notes
- New
manifest-utils.tsprovides clean, reusable utilities - Types are well-defined with
RawWorkflowManifestvsWorkflowManifestdistinction - SWC plugin spec document updated comprehensively
- O(1) lookups by ID is a nice performance improvement
Minor Suggestions (non-blocking)
-
Duplicate
mergeRawManifestfunction - The function exists in bothbase-builder.ts:27-48andswc-esbuild-plugin.ts:26-51. Consider consolidating intomanifest-utils.ts. -
Use of
anytypes inmanifest-utils.ts:20-23- Could use proper typing givenWorkflowManifesttypes are available:type ManifestEntry = { name: string; exports: Record<string, string>; [key: string]: unknown; };
-
Consider marking as breaking in changeset if this affects external tooling that reads
manifest.json. -
Graph lookup fallback - In
addGraphsToWorkflows, the lookup relies onexports.workflowbeing present. Consider checking bothexports.workflowandexports.default.
LGTM! 🚀
| "@workflow/next": patch | ||
| --- | ||
|
|
||
| New and improved `manifest.json` format |
There was a problem hiding this comment.
This is a significant format change. Should this be marked as BREAKING CHANGE per project conventions if external tooling reads manifest.json?
There was a problem hiding this comment.
This is a valid concern. However, the manifest.json format is currently internal to the build tooling and not intended as a public API for external consumers. The format is read by our own runtime and tooling. If there are external tools relying on this format, we should document and version it properly in a separate PR. For now, keeping this as a patch release seems appropriate since it's an internal improvement.
VaguelySerious
left a comment
There was a problem hiding this comment.
web-shared and web o11y code use the manifest and should presumably be updated, CC @karthikscale3
📊 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 | Nitro | Next.js (Turbopack) 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: Next.js (Turbopack) | Nitro | Express workflow with 50 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) Promise.all with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Express | Nitro Promise.all with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Nitro | Express Promise.all with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Nitro | Express 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: Nitro | Next.js (Turbopack) | Express Promise.race with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Express | Nitro Stream Benchmarks (includes TTFB metrics)workflow with stream💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Next.js (Turbopack) | Express SummaryFastest Framework by WorldWinner determined by most benchmark wins
Fastest World by FrameworkWinner determined by most benchmark wins
Column Definitions
Worlds:
|
…and improve graph lookup - Consolidate mergeRawManifest into manifest-utils.ts as shared function - Replace any types with proper ManifestEntry type using generics - Fix graph lookup to check both workflow and default exports
The manifest adapter now detects and handles both formats: - Legacy (pre-1.0.0): file-path keyed structure - New (1.0.0+): ID-keyed structure with exports This ensures the web UI can display workflow graphs from both old and new deployments during the transition period.
TooTallNate
left a comment
There was a problem hiding this comment.
Addressed the backwards compatibility concern for web-shared and web o11y tooling.
The manifest-adapter.ts in the web package now detects and handles both formats:
- Legacy (pre-1.0.0): file-path keyed structure
{ [filePath]: { [workflowName]: { workflowId, graph } } } - New (1.0.0+): ID-keyed structure
{ [workflowId]: { name, exports, graph } }
The adapter auto-detects the format by checking for the presence of name and exports fields in workflow entries. This ensures the web UI can display workflow graphs from both old and new deployments during the transition period.
See commit e5b5cff for the changes.

Overview
The
manifest.jsonformat has been inverted from a file-path-keyed structure to an ID-keyed structure. This makes it easier to look up entries by their ID and allows manifest entries to be passed directly to APIs likestart().Old Format (file-path-keyed)
New Format (ID-keyed)
Key Changes
step//./path//name)namefieldexportsobject with condition keysBenefits
start()since they includeworkflowIdexportsobject maps bundle conditions (default,workflow) to source filesMigration Notes
Code that previously accessed the manifest like this:
Should now use: