The Vercel Output API, when used with custom frameworks, doesn’t just generate build artifacts; it orchestrates a distributed, event-driven compilation process that can be paused, resumed, and even rerouted.
Let’s see this in action. Imagine you’re building a framework that needs to process images, transpile JavaScript, and generate static HTML. Instead of a monolithic build script, the Output API breaks this down into discrete, actionable steps.
Consider this simplified vercel.json and a hypothetical framework output:
vercel.json:
{
"framework": "my-custom-framework",
"outputDirectory": "dist",
"plugins": [
{
"use": "@vercel/static-build",
"config": {
"includeFiles": [
"**/*.{js,jsx,ts,tsx,html,css,png,jpg,jpeg,gif,svg}"
]
}
}
]
}
When Vercel runs your custom framework, it doesn’t just npm run build. It invokes your framework’s build entry point, expecting it to emit structured output that Vercel understands. This output is typically a stream of JSON objects, each representing a specific build event.
Here’s a snippet of what that output might look like, conceptually:
{
"type": "nextjs", // Or your custom framework identifier
"framework": "my-custom-framework",
"version": "1.0.0",
"buildId": "...",
"output": {
"entries": [
{
"name": "app.js",
"type": "asset",
"path": "static/js/app.js",
"digest": "sha256-...",
"size": 10240
},
{
"name": "index.html",
"type": "route",
"path": "index.html",
"digest": "sha256-...",
"size": 2048
}
]
},
"startTime": 1678886400000,
"endTime": 1678886410000
}
The key here is the type field. Vercel uses this to understand what kind of output it’s receiving. For custom frameworks, you’d define your own types. For example, you might have:
framework:build-step-start: Indicates the beginning of a specific build phase.framework:asset-generated: A file asset has been created (e.g., a JS bundle, CSS file).framework:route-generated: A page or API route has been generated.framework:build-error: An error occurred during the build.framework:build-complete: The entire build process has finished successfully.
Your custom framework’s build process would be responsible for emitting these events. This allows Vercel to:
- Track Progress: Understand which parts of the build are done and which are pending.
- Handle Failures: Gracefully report errors with context.
- Optimize Deployment: Know exactly which files to upload and how to serve them.
- Enable Advanced Features: Support features like streaming builds, incremental builds, and custom build caching.
The outputDirectory specified in vercel.json (dist in our example) is where your framework should place the generated files. Vercel then ingests these files based on the asset-generated and route-generated events.
The true power lies in how Vercel interprets these events. It’s not just a file-copying mechanism. For instance, when it sees a route-generated event for index.html, it knows to configure a serverless function or static file handler for that path. If it sees an asset-generated event for app.js, it knows this is a dependency that needs to be served efficiently.
You control this by defining how your framework emits these structured outputs. This often involves integrating with bundlers (like Webpack or esbuild) and ensuring their output is translated into the Vercel Output API format. For example, if your bundler reports a new chunk being generated, your framework’s Vercel integration would emit a framework:asset-generated event.
The most surprising aspect is how this event stream allows for distributed builds. Vercel can, in theory, distribute different build steps to different workers based on these events, creating a highly scalable and resilient build infrastructure. It’s not a single process running top-to-bottom; it’s a choreography of independent tasks.
The digest field in the output is crucial for Vercel’s caching strategy. By providing a cryptographic hash of the file content, Vercel can determine if a file has changed since the last build, skipping redundant uploads and speeding up subsequent deployments.
When you’re building a custom framework integration, you’re not just telling Vercel what files to deploy, but how they were produced and what role they play in your application’s architecture. This level of introspection is what enables Vercel’s advanced deployment optimizations.
You’ll next encounter the challenge of handling complex asset dependencies and ensuring your framework’s output events accurately reflect the final state of your application for Vercel’s deployment engine.