• Product Introduction
  • Quick Start
    • Importing a Git Repository
    • Starting From a Template
    • Direct Upload
    • Start with AI
  • Framework Guide
    • Frontends
      • Vite
      • React
      • Vue
      • Other Frameworks
    • Backends
    • Full-stack
      • Next.js
      • Nuxt
      • Astro
      • React Router
      • SvelteKit
      • TanStack Start
      • Vike
    • Custom 404 Page
  • Project Guide
    • Project Management
    • edgeone.json
    • Configuring Cache
    • Building Output Configuration
    • Error Codes
  • Build Guide
  • Deployment Guide
    • Overview
    • Create Deploys
    • Manage Deploys
    • Deploy Button
    • Using Github Actions
    • Using Gitlab CI/CD
    • Using CNB Plugin
    • Using IDE PlugIn
    • Using CodeBuddy IDE
  • Domain Management
    • Overview
    • Custom Domain
    • HTTPS Configuration
      • Overview
      • Apply for Free Certificate
      • Using Managed SSL Certificate
    • Configure DNS CNAME Record
  • Observability
    • Overview
    • Metric Analysis
    • Log Analysis
  • Pages Functions
    • Overview
    • Edge Functions
    • Cloud Functions
      • Overview
      • Node.js
      • Python
      • Go
  • Middleware
  • KV Storage
  • Edge AI
  • API Token
  • EdgeOne CLI
  • Pages MCP
  • Pages Skills
  • Message Notification
  • Integration Guide
    • AI
      • Dialogue Large Models Integration
      • Large Models for Images Integration
    • Database
      • Supabase Integration
      • Pages KV Integration
    • Ecommerce
      • Shopify Integration
      • WooCommerce Integration
    • Payment
      • Stripe Integration
      • Integrating Paddle
    • CMS
      • WordPress Integration
      • Contentful Integration
      • Sanity Integration
      • Payload Integration
    • Authentication
      • Supabase Integration
      • Clerk Integration
  • Best Practices
    • AI Dialogue Deployment: Deploy Project with One Sentence Using Skill
    • Using General Large Model to Quickly Build AI Application
    • Use the DeepSeek model to quickly build a conversational AI site
    • Building an Ecommerce Platform with Shopify
    • Building a SaaS Site Using Supabase and Stripe
    • Building a Company Brand Site Quickly
    • How to Quickly Build a Blog Site
  • Migration Guides
    • Migrating from Vercel to EdgeOne Pages
    • Migrating from Cloudflare Pages to EdgeOne Pages
    • Migrating from Netlify to EdgeOne Pages
  • Troubleshooting
  • FAQs
  • Contact Us
  • Release Notes

Building Output Configuration

The build output configuration is a file system-based standard for defining framework artifacts. It provides a standardized method to enable framework adapters to unify build results in a format output and deploy to the EdgeOne Pages platform.

Overview

The build output API closely corresponds to EdgeOne Pages product features in a clear and easy-to-understand way. If you are a framework author hoping for seamless integration with EdgeOne Pages, you can use this reference to learn which files the framework should output to the .edgeone directory.
You can create your own .edgeone directory and fill it according to this standard. In the following text, we will provide detailed instructions so that developers can understand how to use the build output for their own framework adapter.

Directory Structure in Its Entirety


Developers need to focus on the core in .edgeone/cloud-functions/ssr-node/config.json. The config.json file contains deployment configuration messages.
For Web full-stack framework services, the entry file should be named handler.js.

Supported Fields in config.json

version

version attribute indicates the implemented Build Output API version. The document description version is 3.
{
"version": 3
}

routes

routes attribute describes routing rules applied to deployment. Routing can be used to point specific URL paths to other paths under deployment, attach response headers to paths, implement redirection and various routing related use cases.
type Route = Source | Handler;

Source route

type Source = {
src: string;
dest?: string;
headers?: Record<string, string>;
methods?: string[];
continue?: boolean;
status?: number;
has?: HasField[];
missing?: HasField[];
};
Field
Type
Required
Description
src
String
Yes
A regular expression compatible with RE2, used to match each passed in path name (excluding query string).
dest
String
No
Rewrite the target path or complete URL (including querystring), supporting capture groups $1, $2. If not provided, directly use the original path from the client request.
headers
Record <string, string>
No
A group of HTTP response headers that apply to the response.
methods
String[]
No
A group of HTTP method types. If not provided, any HTTP method request will become a candidate for the route.
continue
Boolean
No
A boolean value used to change matching behavior. If it is true, the route will continue matching follow-up rules even if src matches.
status
Number
No
The status code of the response. It must be used in conjunction with headers.Location to implement redirection. Location supports capture groups $1, $2, etc.
has
HasField[]
No
HTTP request conditions (header/cookie/query/host) that must be met for application routing.
missing
HasField[]
No
HTTP request conditions (reverse condition matching) that must fail to satisfy for application routing.
Source route: HasField
type HasField = Array<
{ type: 'host', value: string }
{
type: 'header' | 'cookie' | 'query';
key: string;
value?: string;
}
>;
Field
Type
Required
Description
type
"host" | "header" | "cookie" | "query"
Yes
Confirm the HasField Type.
key
String
No
header, cookie, and query are required. The matching key name.
value
String
No
Value to match (support regular expressions).

Handler route

The routing system uses the handle value to identify the routing stage boundary. EdgeOne only supports handle: "filesystem".
type Handler = {
handle: 'filesystem';
};
Field
Type
Required
Description
handle
"filesystem"
Yes
The boundary tag for static file search. Only supports "filesystem".
{
"version": 3,
"routes": [
// Stage 1: Preprocessing stage (before filesystem)
// Use: redirect, set response header
{ "src": "^/_next/static/(.*)$", "headers": { "cache-control": "public, max-age=31536000, immutable" } },

{ "handle": "filesystem" },

// Phase 2: Back-to-origin stage (after filesystem)
// For: API routing, SSR webpage, function call
{ "src": "^/api/(.*)$", "dest": "/api/$1" },
{ "src": "/.*" }
]
}
Note:
handle: "filesystem" The routing configuration format before and after is identical, no special processing required.

Output Location

Based on the Builder type, write corresponding files to different directories. The full-stack Web framework is placed in cloud-functions/ssr-node.
Builder Type
Output Location
static resource
assets/
Node.js SSR functions
cloud-functions/ssr-node/
Node.js API functions
cloud-functions/api-node/
Go API functions
cloud-functions/api-go/
Python API functions
cloud-functions/api-python/
Edge functions
edge-functions/

Node.js API

Source code directory structure:
cloud-functions/
├── api/
│ ├── users.js
│ └── posts/[id].js
└── hello.js
Build output directory structure:

cloud-functions/
├── api-node/
│ ├── node_modules/
│ ├── index.mjs
│ └── config.json
...
generated config.json:

{
"version": 3,
"routes": [
{ "src": "^/api/users$", "dest": "/api/users" },
{ "src": "^/api/posts/([^/]+)$", "dest": "/api/posts/$1" },
{
"src": "^/hello-node$",
"methods": [
"GET",
"POST",
"PUT",
"DELETE",
"PATCH",
"HEAD",
"OPTIONS"
]
}
]
}

Go API

Handler Mode

Source code directory structure:
cloud-functions/
├── api/
│ ├── users.go
│ └── posts/[id].go
├── health.go
├── go.mod
└── go.sum
Build output directory structure:
cloud-functions/api-go
├── config.json
├── go.mod
└── main.go // output product entry file name fixed as main in handler mode
generated config.json:
{
"version": 3,
"routes": [
{
"src": "^/api/users/?$"
},
{
"src": "^/health/?$"
},
{
"src": "^/api/posts/([^/]+)/?$"
}
]
}

Framework Mode

Source code directory structure:
cloud-functions/
├── api.go
├── go.mod
└── go.sum
Build output directory structure:
cloud-functions/api-go
├── config.json
├── go.mod
└── api.go //This file has the same name as the entry file
generated config.json:
{
"version": 3,
"framework": "gin",
"routes": [
{
"src": "^/api(.*)$"
}
]
}

Python API

Handler Mode

Source code directory structure:
cloud-functions/
├── api/
│ └── users.py
├── hello.py
└── requirements.txt (optional)
Build output directory structure:
cloud-functions/api-python
├── config.json
├── app.py // Entry file, fixed as app.py
├── requirements.txt
├── api/
│ └── users.py
├── hello.py
└── <dependencies>/ // Third-party dependency package (installed under the product directory)
generated config.json:
{
"vsersion": 3,
"routes": [
{
"src": "^/api/users$"
},
{
"src": "^/hello$"
}
]
}

Framework Mode

Source code directory structure (using FastAPI as an example):
cloud-functions/
├── demo-fastapi.py
└── requirements.txt (optional)
Build output directory structure:
cloud-functions/api-python
├── config.json
├── app.py // Entry file, fixed as app.py
├── requirements.txt
├── demo-fastapi.py
└── <dependencies>/ // Third-party dependency package (such as fastapi, uvicorn)
generated config.json:
{
"version": 3,
"routes": [
{
"src": "^/demo-fastapi$"
}
]
}

Common Scenes

URL Redirect

// Fixed path redirection
{ "src": "^/old-path$", "headers": { "Location": "/new-path" }, "status": 301 }

// Real-time path redirection (support capture group)
{ "src": "^/blog/(.*)$", "headers": { "Location": "/posts/$1" }, "status": 301 }

// Full URL redirect
{ "src": "^/external$", "headers": { "Location": "https://example.com/page" }, "status": 302 }
Note:
Redirect using headers.Location + status composite
Location can be a relative path (such as /new-path) or a complete URL
Location can use capture group variables like $1, $2 to implement dynamic redirection.

Catch-all

Rewrite all requests to the root path index.html, usually used for single-page applications (SPA).
{
"src": "/.*",
"dest": "index.html"
}

Set Response Header

{
"src": "^/_next/static/(.*)$",
"headers": { "cache-control": "public, max-age=31536000, immutable" }
}

Clean URLs

{ "src": "^/about$", "dest": "/about.html" }

Dynamic Routing

{ "src": "^/blog/([^/]+)$", "dest": "/blog/$1" }
Note: Use regular expression capture group $1 to transmit dynamic parameter.

Complete Example

{
"version": 3,
"routes": [
{
"src": "^/([^.]+[^/.])$",
"dest": "/$1/",
"continue": true
},
{
"src": "/test-ssg",
"headers": {
"Cache-Control": "max-age=3600"
}
},
{
"src": "/api/cookies-test",
"headers": {
"Cache-Control": "public, max-age=60, stale-while-revalidate=300"
}
},
{
"handle": "filesystem"
},
{
"src": "^/about$",
"dest": "/about.html"
},
{
"src": "^/blog/([^/]+)$",
"dest": "/blog/$1"
},
{
"src": "^/api/cookies-test-cache$"
},
{
"src": "^/api/seconde/query-test$"
},
{
"src": "^/api/cookies-test$"
},
{
"src": "^/posts/([^/]+)$"
},
{
"src": "^/auth$"
},
{
"src": "^/$"
},
{
"src": "^/(.*)$"
}
]
}

Current Limitation

The Web full-stack framework API routing is uniformly specified to execute in Node Server and unable to execute in Edge Server. If needed, you can use Edge Functions in the framework.

ai-agent
You can ask me like
How to Get Started with EdgeOne Pages?