EdgeOne Pages Development Guide Develop full-stack applications on EdgeOne Pages — Edge Functions, Cloud Functions (Node.js / Go / Python), and Middleware. When to use this skill - Creating APIs, serverless functions, or backend logic on EdgeOne Pages - Adding middleware for request interception, redirects, auth guards, or A/B testing - Building full-stack apps with static frontend + server-side functions - Using KV Storage for edge-side persistent data - Setting up WebSocket endpoints (Node.js runtime) - Integrating Express, Koa, Gin, Echo, Flask, FastAPI, or Django on EdgeOne Pages - Debugg…

] };\n```\n\n## Common patterns\n\n### URL Redirect\n\n```javascript\nexport function middleware(context) {\n const url = new URL(context.request.url);\n\n if (url.pathname === '/old-page') {\n return context.redirect('/new-page', 301);\n }\n return context.next();\n}\n```\n\n### URL Rewrite (transparent proxy)\n\n```javascript\nexport function middleware(context) {\n const url = new URL(context.request.url);\n\n if (url.pathname.startsWith('/blog')) {\n return context.rewrite('/content' + url.pathname);\n }\n return context.next();\n}\n```\n\n### Add request headers\n\n```javascript\nexport function middleware(context) {\n return context.next({\n headers: {\n 'x-request-id': crypto.randomUUID(),\n 'x-client-ip': context.clientIp,\n 'x-country': context.geo.countryCodeAlpha2,\n },\n });\n}\n```\n\n### Auth guard\n\n```javascript\nexport const config = {\n matcher: ['/api/:path*', '/admin/:path*'],\n};\n\nexport function middleware(context) {\n const token = context.request.headers.get('Authorization');\n if (!token || !token.startsWith('Bearer ')) {\n return new Response(JSON.stringify({ error: 'Unauthorized' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n return context.next();\n}\n```\n\n### Geo-based routing\n\n```javascript\nexport function middleware(context) {\n const country = context.geo.countryCodeAlpha2;\n\n if (country === 'CN') {\n return context.rewrite('/zh' + new URL(context.request.url).pathname);\n }\n return context.next();\n}\n```\n\n### A/B Testing\n\n```javascript\nexport function middleware(context) {\n const url = new URL(context.request.url);\n\n if (url.pathname === '/landing') {\n const variant = Math.random() \u003c 0.5 ? '/landing-a' : '/landing-b';\n return context.rewrite(variant);\n }\n return context.next();\n}\n```\n\n### Direct JSON response\n\n```javascript\nexport function middleware(context) {\n const url = new URL(context.request.url);\n\n if (url.pathname === '/api/health') {\n return new Response(JSON.stringify({ status: 'ok', timestamp: Date.now() }), {\n headers: { 'Content-Type': 'application/json' },\n });\n }\n return context.next();\n}\n```\n\n## GeoProperties\n\nAvailable on `context.geo`:\n\n| Property | Type | Example |\n|----------|------|---------|\n| `countryName` | string | Singapore |\n| `countryCodeAlpha2` | string | SG |\n| `countryCodeAlpha3` | string | SGP |\n| `regionName` | string | — |\n| `cityName` | string | Singapore |\n| `latitude` | number | 1.29027 |\n| `longitude` | number | 103.851959 |\n| `asn` | number | 132203 |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4363,"content_sha256":"23498f8295a6f0ca442c8fad456fdc30c928cdabe6d08a3c8d158d226f548f83"},{"filename":"references/node-functions.md","content":"# Node.js Functions\n\nNode.js v20.x runtime functions under `cloud-functions/`. Full npm ecosystem support. Ideal for complex backend logic, database access, Express/Koa frameworks, and WebSocket.\n\n> **Runtime:** Node.js v20.x — supports ES modules, full npm ecosystem, and WebSocket.\n\n## Basic function\n\nFile: `cloud-functions/api/data.js`\n\n```javascript\nexport function onRequestGet(context) {\n return Response.json({\n message: 'Hello from Node.js Functions!',\n region: context.server.region,\n });\n}\n\nexport async function onRequestPost(context) {\n const body = await context.request.json();\n // Process body...\n return Response.json({ received: body }, { status: 201 });\n}\n```\n\nAccess: `GET /api/data`, `POST /api/data`\n\n## Handler methods\n\n| Handler | HTTP Method |\n|---------|-------------|\n| `onRequest(context)` | All methods (GET, POST, PATCH, PUT, DELETE, HEAD, OPTIONS) |\n| `onRequestGet(context)` | GET |\n| `onRequestPost(context)` | POST |\n| `onRequestPatch(context)` | PATCH |\n| `onRequestPut(context)` | PUT |\n| `onRequestDelete(context)` | DELETE |\n| `onRequestHead(context)` | HEAD |\n| `onRequestOptions(context)` | OPTIONS |\n\nAll handlers return `Response | Promise\u003cResponse>`.\n\n## EventContext object\n\n```javascript\nexport function onRequest(context) {\n const {\n uuid, // EO-LOG-UUID unique request identifier\n request, // Standard Request object\n params, // Dynamic route params, e.g. { id: \"123\" }\n env, // Environment variables from Pages console\n clientIp, // Client IP address\n server, // { region: string, requestId: string }\n geo, // Client geolocation info\n } = context;\n\n return new Response('OK');\n}\n```\n\n## Using npm packages\n\n```javascript\n// cloud-functions/api/data.js\nimport mysql from 'mysql2/promise';\n\nexport async function onRequestGet(context) {\n const connection = await mysql.createConnection({\n host: context.env.DB_HOST,\n user: context.env.DB_USER,\n password: context.env.DB_PASSWORD,\n database: context.env.DB_NAME,\n });\n\n const [rows] = await connection.execute('SELECT * FROM users LIMIT 10');\n await connection.end();\n\n return Response.json({ users: rows });\n}\n```\n\n⚠️ Install dependencies in project root `package.json` — the platform builds them automatically.\n\n## Express integration\n\nFile: `cloud-functions/api/[[default]].js`\n\n```javascript\nimport express from 'express';\n\nconst app = express();\napp.use(express.json());\n\n// Add logging middleware\napp.use((req, res, next) => {\n console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);\n next();\n});\n\n// Root route → GET /api/\napp.get('/', (req, res) => {\n res.json({ message: 'Hello from Express!' });\n});\n\n// GET /api/users/:id\napp.get('/users/:id', (req, res) => {\n res.json({ userId: req.params.id });\n});\n\n// POST /api/users\napp.post('/users', (req, res) => {\n res.status(201).json({ user: req.body });\n});\n\n// MUST export the app — do NOT call app.listen()\nexport default app;\n```\n\n**Key rules for Express/Koa:**\n- All framework routes go in **one function file** using `[[...]]` naming pattern (e.g. `[[default]].js`)\n- MUST `export default app` — do NOT call `app.listen()` or start HTTP server\n- No need to set up port listening — the platform handles it\n\n## Koa integration\n\nFile: `cloud-functions/api/[[default]].js`\n\n```javascript\nimport Koa from 'koa';\nimport Router from '@koa/router';\nimport bodyParser from 'koa-bodyparser';\n\nconst app = new Koa();\nconst router = new Router();\n\napp.use(bodyParser());\n\nrouter.get('/hello', (ctx) => {\n ctx.body = { message: 'Hello from Koa!' };\n});\n\nrouter.post('/data', (ctx) => {\n ctx.body = { received: ctx.request.body };\n});\n\napp.use(router.routes());\napp.use(router.allowedMethods());\n\n// MUST export — do NOT call app.listen()\nexport default app;\n```\n\n## File-system Routing\n\n```\ncloud-functions/\n├── index.js\n├── hello-pages.js\n├── api/\n│ ├── users/\n│ │ ├── list.js\n│ │ ├── geo.js\n│ │ └── [id].js\n│ ├── visit/\n│ │ └── index.js\n│ └── [[default]].js\n```\n\n| File path | Route |\n|-----------|-------|\n| `cloud-functions/index.js` | `example.com/` |\n| `cloud-functions/hello-pages.js` | `example.com/hello-pages` |\n| `cloud-functions/api/users/list.js` | `example.com/api/users/list` |\n| `cloud-functions/api/users/[id].js` | `example.com/api/users/:id` |\n| `cloud-functions/api/[[default]].js` | `example.com/api/*` (catch-all) |\n\n> **Notes:**\n> - Trailing slash `/` is optional: `/hello-pages` and `/hello-pages/` both route to `cloud-functions/hello-pages.js`\n> - If a Node.js route conflicts with a static asset route, the static asset takes priority\n> - Routes are case-sensitive\n\n### Express/Koa framework routing\n\n```\ncloud-functions/\n└── express/\n └── [[default]].js # Express/Koa entry file, all routes inside\n```\n\n- All routes consolidated in **one function file** with `[[...]]` naming\n- No HTTP server startup needed — just export the framework instance\n- The builder identifies the file as a function only when `export default app` is present\n\n## Dynamic Routes\n\n```javascript\n// cloud-functions/api/users/[id].js\nexport function onRequestGet(context) {\n return new Response(`User id is ${context.params.id}`);\n}\n```\n\n| File path | Example URL | Match? |\n|-----------|-------------|--------|\n| `api/users/[id].js` | `/api/users/1024` | ✅ Yes |\n| `api/users/[id].js` | `/api/users/vip/1024` | ❌ No |\n| `api/[[default]].js` | `/api/books/list` | ✅ Yes |\n| `api/[[default]].js` | `/api/1024` | ✅ Yes |\n\n## WebSocket\n\nFile: `cloud-functions/api/ws.js`\n\n```javascript\nexport function onRequestGet(context) {\n const { request } = context;\n\n // Check for WebSocket upgrade\n const upgradeHeader = request.headers.get('Upgrade');\n if (upgradeHeader !== 'websocket') {\n return new Response('Expected WebSocket', { status: 426 });\n }\n\n // Create WebSocket pair\n const { socket, response } = new WebSocketPair();\n\n socket.addEventListener('message', (event) => {\n socket.send(`Echo: ${event.data}`);\n });\n\n socket.addEventListener('close', () => {\n console.log('WebSocket closed');\n });\n\n return response;\n}\n```\n\n## Local Development\n\n```bash\nnpm install -g edgeone # Install CLI\nedgeone pages dev # Start local dev server on port 8088\n# Push to remote repo to deploy\n```\n\n## Limits\n\n| Resource | Limit |\n|----------|-------|\n| Code package size | 128 MB |\n| Request body | 6 MB |\n| Wall clock time | 120 seconds |\n| Runtime | Node.js v20.x |\n\n⚠️ Do NOT store persistent files locally — use external storage (e.g. Tencent Cloud COS) for persistent data.\n\n## Template Projects\n\n- **MySQL connection**: [mysql-template](https://github.com/TencentEdgeOne/mysql-template/) | [Preview](https://mysql-template.edgeone.run)\n- **Express**: [express-template](https://github.com/TencentEdgeOne/express-template/) | [Preview](https://express-template.edgeone.run)\n- **Koa**: [koa-template](https://github.com/TencentEdgeOne/koa-template/) | [Preview](https://koa-template.edgeone.run)\n- **AI Voice Chat (WebSocket)**: [pages-ai-voice-chat](https://github.com/TencentEdgeOne/pages-ai-voice-chat) | [Preview](https://pages-ai-voice-chat.edgeone.site)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7299,"content_sha256":"341b2cfdfcc0a006e8428eb53acf4ff96a5079f3b4012268322f281860896d82"},{"filename":"references/python-functions.md","content":"# Python Functions\n\nPython 3.10 runtime functions under `cloud-functions/`. Supports Handler class, WSGI (Flask/Django), and ASGI (FastAPI/Sanic) modes with automatic dependency detection.\n\n> **Runtime:** Python 3.10 — auto-detects framework, auto-installs dependencies, no manual configuration needed.\n\n## Development Modes\n\n| Mode | Use Case | Routing | Framework |\n|------|----------|---------|-----------|\n| **Handler** | Simple APIs, Serverless style | File-system routing (file = route) | None (standard `BaseHTTPRequestHandler`) |\n| **WSGI Framework** | Full Web apps, RESTful APIs | Framework built-in routing | Flask, Django |\n| **ASGI Framework** | Full Web apps, RESTful APIs | Framework built-in routing | FastAPI, Sanic |\n\n## Handler Mode\n\nFile: `cloud-functions/api/hello.py`\n\n```python\nfrom http.server import BaseHTTPRequestHandler\n\nclass handler(BaseHTTPRequestHandler):\n\n def do_GET(self):\n self.send_response(200)\n self.send_header('Content-Type', 'application/json')\n self.end_headers()\n self.wfile.write('{\"message\": \"Hello from Python Functions!\"}'.encode('utf-8'))\n```\n\nAccess: `GET /api/hello`\n\n**Key rules for Handler mode:**\n- Class must be named `handler` (lowercase) and inherit from `BaseHTTPRequestHandler`\n- Implement `do_GET`, `do_POST`, `do_PUT`, `do_DELETE` etc. for different HTTP methods\n\n### Handling POST requests\n\n```python\n# cloud-functions/api/users/index.py\nfrom http.server import BaseHTTPRequestHandler\nimport json\n\nclass handler(BaseHTTPRequestHandler):\n\n def do_POST(self):\n content_length = int(self.headers.get('Content-Length', 0))\n body = self.rfile.read(content_length).decode('utf-8')\n data = json.loads(body) if body else {}\n\n self.send_response(201)\n self.send_header('Content-Type', 'application/json')\n self.end_headers()\n response = json.dumps({'message': 'Created', 'data': data})\n self.wfile.write(response.encode('utf-8'))\n```\n\n### Handler class attributes\n\n| Attribute/Method | Type | Description |\n|-----------------|------|-------------|\n| `self.path` | `str` | Request path (with query params) |\n| `self.command` | `str` | HTTP method (GET, POST, etc.) |\n| `self.headers` | `dict-like` | Request headers |\n| `self.rfile` | `file` | Request body input stream |\n| `self.wfile` | `file` | Response body output stream |\n| `self.send_response(code)` | method | Send HTTP status code |\n| `self.send_header(key, value)` | method | Send response header |\n| `self.end_headers()` | method | End response headers |\n\n### Getting query parameters\n\n```python\n# cloud-functions/api/search.py\nfrom http.server import BaseHTTPRequestHandler\nfrom urllib.parse import urlparse, parse_qs\n\nclass handler(BaseHTTPRequestHandler):\n\n def do_GET(self):\n parsed = urlparse(self.path)\n query_params = parse_qs(parsed.query)\n name = query_params.get('name', ['Guest'])[0]\n\n self.send_response(200)\n self.send_header('Content-Type', 'application/json')\n self.end_headers()\n self.wfile.write(f'{{\"hello\": \"{name}\"}}'.encode('utf-8'))\n```\n\n## Flask Framework (WSGI)\n\nFile: `cloud-functions/api/index.py`\n\n```python\nfrom flask import Flask, jsonify, request\n\napp = Flask(__name__)\n\[email protected]('/users', methods=['GET'])\ndef get_users():\n return jsonify({\n 'users': [\n {'id': 1, 'name': 'Alice'},\n {'id': 2, 'name': 'Bob'}\n ]\n })\n\[email protected]('/users', methods=['POST'])\ndef create_user():\n data = request.get_json()\n return jsonify({'message': 'User created', 'user': data}), 201\n```\n\nAccess: `GET /api/users`, `POST /api/users`\n\n> **Route prefix stripping**: The runtime auto-strips the file-system route prefix. `api/index.py` → prefix `/api`, so request `/api/users` becomes `/users` inside Flask. Define framework routes as relative paths only.\n\n## FastAPI Framework (ASGI)\n\nFile: `cloud-functions/api/index.py`\n\n```python\nfrom fastapi import FastAPI\n\napp = FastAPI()\n\[email protected]('/items')\nasync def list_items():\n return {'items': [{'id': 1, 'name': 'Item A'}, {'id': 2, 'name': 'Item B'}]}\n\[email protected]('/items/{item_id}')\nasync def get_item(item_id: int):\n return {'item_id': item_id, 'name': f'Item {item_id}'}\n\[email protected]('/items')\nasync def create_item(item: dict):\n return {'message': 'Item created', 'item': item}\n```\n\nAccess: `GET /api/items`, `GET /api/items/123`, `POST /api/items`\n\n## File-system Routing\n\n```\ncloud-functions/\n├── api/\n│ ├── index.py\n│ ├── hello.py\n│ ├── users/\n│ │ ├── index.py\n│ │ ├── list.py\n│ │ └── [id].py\n│ ├── orders/\n│ │ └── index.py\n│ └── [[default]].py\n```\n\n| File path | Route |\n|-----------|-------|\n| `cloud-functions/api/index.py` | `example.com/api` |\n| `cloud-functions/api/hello.py` | `example.com/api/hello` |\n| `cloud-functions/api/users/index.py` | `example.com/api/users` |\n| `cloud-functions/api/users/[id].py` | `example.com/api/users/:id` |\n| `cloud-functions/api/[[default]].py` | `example.com/api/*` (catch-all) |\n\n### Route matching priority (high → low)\n\n1. **Static routes** — exact match (e.g. `/api/users/list`)\n2. **Single-level dynamic** — `[param]` matches one segment (e.g. `/api/users/[id]`)\n3. **Catch-all dynamic** — `[[param]]` matches one or more segments (e.g. `/api/[[default]]`)\n\n### Entry file recognition\n\nOnly `.py` files with these patterns are registered as routes:\n- `class handler(BaseHTTPRequestHandler)` — Handler class mode\n- `app = Flask(...)` / `app = FastAPI(...)` — Framework instance mode\n- `application = get_wsgi_application()` — Django WSGI mode\n\nOther `.py` files are treated as helper modules — copied to build output for import but not registered as routes.\n\n## Dynamic Route Parameters\n\n```python\n# cloud-functions/api/users/[id].py\nfrom http.server import BaseHTTPRequestHandler\n\nclass handler(BaseHTTPRequestHandler):\n\n def do_GET(self):\n user_id = self.path.strip('/')\n self.send_response(200)\n self.send_header('Content-Type', 'application/json')\n self.end_headers()\n self.wfile.write(f'{{\"user_id\": \"{user_id}\"}}'.encode('utf-8'))\n```\n\n## Dependency Management\n\n### Auto-detection\n\nThe builder scans all `.py` files under `cloud-functions/` for `import` statements and auto-detects third-party packages. Supported: `fastapi`, `flask`, `django`, `sanic`, `requests`, `httpx`, `pydantic`, `sqlalchemy`, `redis`, `pymongo`, `numpy`, `pandas`, etc.\n\n### Manual dependencies\n\nPlace `requirements.txt` in one of these locations (priority order):\n1. `cloud-functions/requirements.txt` (preferred)\n2. Project root `requirements.txt`\n\n```txt\n# cloud-functions/requirements.txt\nflask>=2.0.0\nredis>=4.0.0\nopenai>=1.0.0\n```\n\nUser-declared versions take highest priority when merged with auto-detected dependencies.\n\n### Excluded directories\n\nThese are not scanned or copied to build output:\n- `__pycache__`, `.git`, `node_modules`\n- `venv`, `.venv` (virtual environments)\n- `scripts` (local test scripts)\n- `tests`, `.pytest_cache` (test files)\n\n## Local Development\n\n```bash\nnpm install -g edgeone # Install CLI\nedgeone pages dev # Start local dev server\n# Push to remote repo to deploy\n```\n\n## Limits\n\n| Resource | Limit |\n|----------|-------|\n| Code package size | 128 MB (including dependencies) |\n| Request body | 6 MB |\n| Wall clock time | 120 seconds |\n| Runtime | Python 3.10 |\n\n⚠️ Do NOT store persistent files locally — use external storage (e.g. Tencent Cloud COS) for persistent data.\n\n## Template Projects\n\n- **Handler mode**: [python-handler-template](https://github.com/TencentEdgeOne/python-handler-template) | [Preview](https://python-handler-template.edgeone.site)\n- **FastAPI**: [python-fastapi-template](https://github.com/TencentEdgeOne/python-fastapi-template) | [Preview](https://python-fastapi-template.edgeone.site)\n- **Flask**: [python-flask-template](https://github.com/TencentEdgeOne/python-flask-template) | [Preview](https://python-flask-template.edgeone.site)\n- **Django**: [python-django-template](https://github.com/TencentEdgeOne/python-django-template) | [Preview](https://python-django-template.edgeone.site)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":8259,"content_sha256":"343d4329f6e81b836b80b5f9ec976fc37ffb055552157c6eab3f94c843e00ae7"},{"filename":"references/recipes.md","content":"# Common Recipes\n\nProject structure templates for typical EdgeOne Pages applications.\n\n## Full-stack app — Node.js (static + API)\n\n```\nmy-app/\n├── index.html # Frontend\n├── style.css\n├── script.js\n├── cloud-functions/\n│ └── api/\n│ ├── users.js # GET/POST /api/users\n│ └── users/[id].js # GET/PUT/DELETE /api/users/:id\n└── package.json\n```\n\nFrontend calls API:\n```javascript\nconst res = await fetch('/api/users');\nconst users = await res.json();\n```\n\n## Full-stack app — Go (Gin framework)\n\n```\nmy-app/\n├── index.html # Frontend\n├── style.css\n├── script.js\n├── cloud-functions/\n│ └── api.go # Gin app — all /api/* routes\n├── go.mod\n└── package.json\n```\n\n**cloud-functions/api.go:**\n```go\npackage main\n\nimport (\n \"net/http\"\n \"github.com/gin-gonic/gin\"\n)\n\nfunc main() {\n r := gin.Default()\n r.GET(\"/users\", listUsersHandler)\n r.POST(\"/users\", createUserHandler)\n r.GET(\"/users/:id\", getUserHandler)\n r.Run(\":9000\")\n}\n```\n\n## Full-stack app — Python (Flask)\n\n```\nmy-app/\n├── index.html # Frontend\n├── style.css\n├── script.js\n├── cloud-functions/\n│ └── api/\n│ └── index.py # Flask app — all /api/* routes\n├── cloud-functions/requirements.txt\n└── package.json\n```\n\n**cloud-functions/api/index.py:**\n```python\nfrom flask import Flask, jsonify, request\n\napp = Flask(__name__)\n\[email protected]('/users', methods=['GET'])\ndef get_users():\n return jsonify({'users': []})\n\[email protected]('/users', methods=['POST'])\ndef create_user():\n data = request.get_json()\n return jsonify({'message': 'Created', 'user': data}), 201\n```\n\n## Full-stack app — Python (FastAPI)\n\n```\nmy-app/\n├── index.html\n├── cloud-functions/\n│ └── api/\n│ └── index.py # FastAPI app — all /api/* routes\n├── cloud-functions/requirements.txt\n└── package.json\n```\n\n**cloud-functions/api/index.py:**\n```python\nfrom fastapi import FastAPI\n\napp = FastAPI()\n\[email protected]('/items')\nasync def list_items():\n return {'items': []}\n\[email protected]('/items/{item_id}')\nasync def get_item(item_id: int):\n return {'item_id': item_id}\n```\n\n## Full-stack app — Go (Handler mode)\n\n```\nmy-app/\n├── index.html\n├── cloud-functions/\n│ └── api/\n│ ├── users/\n│ │ ├── list.go # GET /api/users/list\n│ │ └── [id].go # GET /api/users/:id\n│ └── hello.go # GET /api/hello\n├── go.mod\n└── package.json\n```\n\n## Edge API + KV counter\n\n⚠️ **Prerequisites**: You must enable KV Storage in the console and bind a namespace first. See [kv-storage.md](kv-storage.md) (same directory)\n\n```\nmy-app/\n├── index.html\n├── edge-functions/\n│ └── api/\n│ └── visit.js # Edge function with KV\n└── package.json\n```\n\n**edge-functions/api/visit.js:**\n```javascript\nexport async function onRequest() {\n // ⚠️ my_kv is a global variable (name set when binding namespace in console)\n let count = await my_kv.get('visits') || '0';\n count = String(Number(count) + 1);\n await my_kv.put('visits', count);\n \n return new Response(JSON.stringify({ visits: count }), {\n headers: { 'Content-Type': 'application/json' },\n });\n}\n```\n\n**Setup steps:**\n1. Log in to the EdgeOne Pages console\n2. Go to \"KV Storage\" → click \"Apply Now\"\n3. Create a namespace (e.g. `my-kv-store`)\n4. Bind to project, set variable name to `my_kv`\n5. Deploy or run `edgeone pages dev` to test\n\n## Express full-stack\n\n```\nmy-app/\n├── index.html\n├── cloud-functions/\n│ └── api/\n│ └── [[default]].js # Express app handles all /api/*\n└── package.json\n```\n\n## Middleware + API combo\n\n```\nmy-app/\n├── middleware.js # Auth guard for /api/*\n├── cloud-functions/\n│ └── api/\n│ ├── public.js # No auth needed (matcher excludes it)\n│ └── data.js # Protected by middleware\n└── package.json\n```\n\n## Multi-language Cloud Functions\n\nYou can use different languages in the same `cloud-functions/` directory:\n\n```\nmy-app/\n├── index.html\n├── cloud-functions/\n│ ├── api/\n│ │ ├── users.js # Node.js — /api/users\n│ │ └── hello.py # Python — /api/hello\n│ └── service.go # Go — /service\n├── go.mod\n├── cloud-functions/requirements.txt\n└── package.json\n```\n\n> **Note:** Each file is built and deployed as an independent function with its own runtime. The platform detects the language by file extension.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4789,"content_sha256":"74c7491683dbfb7e9bf420e099a51fb0d33bb2304777a96ab0650b4647da2cbb"},{"filename":"references/troubleshooting.md","content":"# Debugging & Troubleshooting\n\n## General Issues\n\n| Issue | Solution |\n|-------|----------|\n| Function not found / 404 | Check file location matches expected route path under `cloud-functions/` |\n| Env vars not available | Run `edgeone pages env pull` and restart dev server |\n| Hot reload not working | Check you're using `edgeone pages dev`, not a custom dev server |\n| Middleware runs on static assets | Add `config.matcher` to limit middleware to specific paths |\n\n## Edge Functions\n\n| Issue | Solution |\n|-------|----------|\n| `require is not defined` | Edge Functions use ES modules — use `import` instead |\n| npm package fails | Edge Functions don't support npm — move to Cloud Functions (Node.js) |\n| `Response.json()` not available | Use `new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json' } })` |\n| Exceeds CPU limit | Move heavy computation to Cloud Functions (120s limit vs 200ms) |\n\n## KV Storage\n\n| Issue | Solution |\n|-------|----------|\n| KV returns `undefined` | Run `edgeone pages link` first to connect your project |\n| `ReferenceError: my_kv is not defined` | KV not enabled or namespace not bound — enable KV in the console, create namespace, and bind to project |\n| Accessing `context.env.KV` returns `undefined` | KV is a **global variable**, not on `context.env` — use `my_kv.get(...)` directly |\n| KV `get()` returns a Promise | Missing `await` — always `await` KV operations |\n| KV not working in Cloud Functions | KV is only available in Edge Functions — use an external database for Cloud Functions |\n\n## Cloud Functions — Node.js\n\n| Issue | Solution |\n|-------|----------|\n| Express `app.listen()` error | Remove `app.listen()` — export the app directly with `export default app` |\n| WebSocket not connecting | Ensure you're using Cloud Functions (Node.js), not Edge Functions |\n| `res.send()` not working | Non-framework functions return Web `Response` objects, not Express-style `res` |\n| Framework routes not matching | Check entry file uses `[[default]].js` pattern and routes don't include the file-system prefix |\n\n## Cloud Functions — Go\n\n| Issue | Solution |\n|-------|----------|\n| Build fails with Go errors | Ensure `go.mod` exists in project root with correct module path |\n| Handler function not found | Handler mode requires `package handler` with an exported func matching `http.HandlerFunc` signature |\n| Framework routes return 404 | Check entry file name — it determines the URL prefix (e.g. `api.go` → `/api` prefix) |\n| Mixed mode error | Cannot mix Handler and Framework modes — choose one per project |\n| Port binding error in Framework mode | Use `r.Run(\":9000\")` or similar — platform maps the port automatically |\n\n## Cloud Functions — Python\n\n| Issue | Solution |\n|-------|----------|\n| Python file not registered as route | File must contain entry pattern: `class handler(BaseHTTPRequestHandler)`, `app = Flask(...)`, `app = FastAPI(...)`, or `application = get_wsgi_application()` |\n| Import errors / missing dependencies | Add to `cloud-functions/requirements.txt` or project root `requirements.txt` — auto-detect may miss some packages |\n| Flask route returns 404 | Framework routes don't include file-system prefix — use `@app.route('/users')` not `@app.route('/api/users')` for `api/index.py` |\n| FastAPI async issues | Ensure Python 3.10 compatible async patterns — `async def` handlers work natively |\n| Django not working | Use `application = get_wsgi_application()` pattern in entry file |\n| `__pycache__` or `venv` causing issues | These directories are auto-excluded from build — no action needed |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3633,"content_sha256":"69b387ecffa2b6b5c1b39e9cf6bc759f3d3e14218fb2ba0f97d332ed2afbafae"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"EdgeOne Pages Development Guide","type":"text"}]},{"type":"paragraph","content":[{"text":"Develop full-stack applications on ","type":"text"},{"text":"EdgeOne Pages","type":"text","marks":[{"type":"strong"}]},{"text":" — Edge Functions, Cloud Functions (Node.js / Go / Python), and Middleware.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to use this skill","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Creating APIs, serverless functions, or backend logic on EdgeOne Pages","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Adding middleware for request interception, redirects, auth guards, or A/B testing","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Building full-stack apps with static frontend + server-side functions","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Using KV Storage for edge-side persistent data","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Setting up WebSocket endpoints (Node.js runtime)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Integrating Express, Koa, Gin, Echo, Flask, FastAPI, or Django on EdgeOne Pages","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Debugging EdgeOne Pages runtime errors (function failures, middleware issues, KV problems)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Do NOT use for:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Deployment → use ","type":"text"},{"text":"edgeone-pages-deploy","type":"text","marks":[{"type":"code_inline"}]},{"text":" skill","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Next.js / Nuxt middleware or API routes → use the framework's own API, NOT the platform ","type":"text"},{"text":"middleware.js","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generic Express/Koa/Gin/Flask development outside an EdgeOne Pages project","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cloudflare Workers, Vercel Functions, or other platforms","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"How to use this skill (for a coding agent)","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Read the ","type":"text"},{"text":"Decision Tree","type":"text","marks":[{"type":"strong"}]},{"text":" below to pick the correct runtime","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Follow the ","type":"text"},{"text":"Routing","type":"text","marks":[{"type":"strong"}]},{"text":" table to load the relevant reference file","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use the code patterns from that reference to implement the user's request","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"⛔ Critical Rules (never skip)","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Choose the right runtime for the task.","type":"text","marks":[{"type":"strong"}]},{"text":" Follow the Decision Tree — never guess.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Edge Functions run on V8, NOT Node.js.","type":"text","marks":[{"type":"strong"}]},{"text":" Never use Node.js built-in modules (","type":"text"},{"text":"fs","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"path","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"crypto","type":"text","marks":[{"type":"code_inline"}]},{"text":" from Node) or npm packages in Edge Functions.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cloud Functions support three runtimes: Node.js, Go, and Python.","type":"text","marks":[{"type":"strong"}]},{"text":" Place all function files under ","type":"text"},{"text":"cloud-functions/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory. The platform detects the language by file extension (","type":"text"},{"text":".js","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":".ts","type":"text","marks":[{"type":"code_inline"}]},{"text":" → Node.js, ","type":"text"},{"text":".go","type":"text","marks":[{"type":"code_inline"}]},{"text":" → Go, ","type":"text"},{"text":".py","type":"text","marks":[{"type":"code_inline"}]},{"text":" → Python).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Node.js functions return a standard Web ","type":"text","marks":[{"type":"strong"}]},{"text":"Response","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" object","type":"text","marks":[{"type":"strong"}]},{"text":", not ","type":"text"},{"text":"res.send()","type":"text","marks":[{"type":"code_inline"}]},{"text":" — unless using Express/Koa via the ","type":"text"},{"text":"[[default]].js","type":"text","marks":[{"type":"code_inline"}]},{"text":" pattern.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Go Handler mode","type":"text","marks":[{"type":"strong"}]},{"text":" requires ","type":"text"},{"text":"http.HandlerFunc","type":"text","marks":[{"type":"code_inline"}]},{"text":" signature; ","type":"text"},{"text":"Framework mode","type":"text","marks":[{"type":"strong"}]},{"text":" uses standard framework code with auto port/path adaptation.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Python entry files","type":"text","marks":[{"type":"strong"}]},{"text":" are identified by class/app patterns (","type":"text"},{"text":"class handler(BaseHTTPRequestHandler)","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"app = Flask(...)","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"app = FastAPI(...)","type":"text","marks":[{"type":"code_inline"}]},{"text":"). Other ","type":"text"},{"text":".py","type":"text","marks":[{"type":"code_inline"}]},{"text":" files are treated as helper modules.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Middleware is for lightweight request interception only.","type":"text","marks":[{"type":"strong"}]},{"text":" Never put heavy computation or database calls in middleware.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Always use ","type":"text","marks":[{"type":"strong"}]},{"text":"edgeone pages dev","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" for local development.","type":"text","marks":[{"type":"strong"}]},{"text":" Never run a separate dev server for functions — the CLI handles everything on port 8088.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never configure ","type":"text","marks":[{"type":"strong"}]},{"text":"edgeone pages dev","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" as the ","type":"text","marks":[{"type":"strong"}]},{"text":"devCommand","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" in ","type":"text","marks":[{"type":"strong"}]},{"text":"edgeone.json","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" or as the ","type":"text","marks":[{"type":"strong"}]},{"text":"dev","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" script in ","type":"text","marks":[{"type":"strong"}]},{"text":"package.json","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — this causes infinite recursion.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"For framework projects (Next.js, Nuxt, etc.), use the framework's own middleware","type":"text","marks":[{"type":"strong"}]},{"text":" — NOT the platform ","type":"text"},{"text":"middleware.js","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Technology Decision Tree","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Request interception / redirect / rewrite / auth guard / A/B test?\n → Middleware → read references/middleware.md\n\nLightweight API with ultra-low latency (simple logic, no npm)?\n → Edge Functions → read references/edge-functions.md\n\nKV persistent storage? (⚠️ enable KV in console first)\n → Edge Functions + KV Storage → read references/kv-storage.md\n\nComplex backend with npm packages / database / WebSocket?\n → Cloud Functions (Node.js) → read references/node-functions.md\n\nExpress or Koa framework?\n → Cloud Functions (Node.js) with [[default]].js → read references/node-functions.md\n\nHigh-performance API with Go (Gin / Echo / Chi / Fiber)?\n → Cloud Functions (Go) → read references/go-functions.md\n\nPython API with Flask / FastAPI / Django / Sanic?\n → Cloud Functions (Python) → read references/python-functions.md\n\nPure static site with no server-side logic?\n → No functions needed — just deploy static files\n\nNeed a project structure template?\n → read references/recipes.md","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Runtime Comparison","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Feature","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Edge Functions","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cloud Functions (Node.js)","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cloud Functions (Go)","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cloud Functions (Python)","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Middleware","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Runtime","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"V8 (like CF Workers)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Node.js v20.x","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Go 1.26+","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Python 3.10","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"V8 (edge)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"npm/packages","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌ Not supported","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"✅ Full npm ecosystem","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"✅ Go modules","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"✅ pip (auto-detect)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌ Not supported","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Max code size","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"5 MB","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"128 MB","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"128 MB","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"128 MB (incl. deps)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Part of edge bundle","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Max request body","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"1 MB","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"6 MB","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"6 MB","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"6 MB","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"N/A (passes through)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Max CPU / wall time","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"200 ms CPU","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"120 s wall clock","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"120 s wall clock","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"120 s wall clock","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Lightweight only","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"KV Storage","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"✅ Yes (global variable)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌ No","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌ No","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌ No","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌ No","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WebSocket","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌ No","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"✅ Yes","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌ No","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌ No","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌ No","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Framework support","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"—","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Express, Koa","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Gin, Echo, Chi, Fiber","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Flask, FastAPI, Django, Sanic","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"—","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use case","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Lightweight APIs, edge compute","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Complex APIs, full-stack","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"High-perf APIs, compiled speed","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Data science, ML, rapid prototyping","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Request preprocessing","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Cloud Functions — Language Comparison","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Feature","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Node.js","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Go","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Python","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"File extension","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":".js","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":".ts","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":".go","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":".py","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Handler style","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"export function onRequest(ctx)","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"Response","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"func Handler(w, r)","type":"text","marks":[{"type":"code_inline"}]},{"text":" (Handler) or ","type":"text"},{"text":"func main()","type":"text","marks":[{"type":"code_inline"}]},{"text":" (Framework)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"class handler(BaseHTTPRequestHandler)","type":"text","marks":[{"type":"code_inline"}]},{"text":" or framework app instance","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Framework mode","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Express/Koa via ","type":"text"},{"text":"[[default]].js","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Gin/Echo/Chi/Fiber via entry ","type":"text"},{"text":".go","type":"text","marks":[{"type":"code_inline"}]},{"text":" file","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Flask/FastAPI/Django via entry ","type":"text"},{"text":".py","type":"text","marks":[{"type":"code_inline"}]},{"text":" file","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dependency management","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"package.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" (npm)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"go.mod","type":"text","marks":[{"type":"code_inline"}]},{"text":" (auto)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"requirements.txt","type":"text","marks":[{"type":"code_inline"}]},{"text":" + auto-detect","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dev modes","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Handler / Framework","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Handler / Framework","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Handler / WSGI / ASGI","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Routing","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Task","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Read","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Edge Functions (lightweight APIs, V8 runtime, KV Storage)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/edge-functions.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/edge-functions.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"KV Storage (persistent key-value storage on edge)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/kv-storage.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/kv-storage.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cloud Functions — Node.js (npm, database, Express/Koa, WebSocket)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/node-functions.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/node-functions.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cloud Functions — Go (Gin, Echo, Chi, Fiber, net/http)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/go-functions.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/go-functions.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cloud Functions — Python (Flask, FastAPI, Django, Sanic, Handler)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/python-functions.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/python-functions.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Middleware (redirects, rewrites, auth guards, A/B testing)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/middleware.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/middleware.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Project structure templates and common recipes","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/recipes.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/recipes.md","title":null}}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Debugging and troubleshooting","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/troubleshooting.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/troubleshooting.md","title":null}}]}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Environment Setup","type":"text"}]},{"type":"paragraph","content":[{"text":"Before executing ","type":"text"},{"text":"any","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"edgeone","type":"text","marks":[{"type":"code_inline"}]},{"text":" CLI command (","type":"text"},{"text":"pages init","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"pages dev","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"pages link","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"pages env pull","type":"text","marks":[{"type":"code_inline"}]},{"text":", etc.), set the following environment variable in the current shell session:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"export PAGES_SOURCE=skills","type":"text"}]},{"type":"paragraph","content":[{"text":"Or prefix each command inline:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"PAGES_SOURCE=skills edgeone pages dev","type":"text"}]},{"type":"paragraph","content":[{"text":"This tells the platform that the command is triggered from an AI skill context.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Project Setup (Quick Start)","type":"text"}]},{"type":"paragraph","content":[{"text":"Initialize the project:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"export PAGES_SOURCE=skills # Required before any edgeone command\nedgeone pages init","type":"text"}]},{"type":"paragraph","content":[{"text":"Start local development:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"edgeone pages dev # Serves everything on http://localhost:8088/","type":"text"}]},{"type":"paragraph","content":[{"text":"Link project (required for KV & env vars):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"edgeone pages link","type":"text"}]},{"type":"paragraph","content":[{"text":"Manage environment variables:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"edgeone pages env pull # Pull from console to local .env","type":"text"}]},{"type":"paragraph","content":[{"text":"Access env vars in functions via ","type":"text"},{"text":"context.env.KEY","type":"text","marks":[{"type":"code_inline"}]},{"text":" (Node.js), ","type":"text"},{"text":"os.Getenv(\"KEY\")","type":"text","marks":[{"type":"code_inline"}]},{"text":" (Go), or ","type":"text"},{"text":"os.environ.get(\"KEY\")","type":"text","marks":[{"type":"code_inline"}]},{"text":" (Python).","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"For detailed project structures and recipes, see ","type":"text"},{"text":"references/recipes.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/recipes.md","title":null}}]},{"text":".","type":"text"}]}]},"metadata":{"date":"2026-06-05","name":"edgeone-pages-dev","author":"@skillopedia","source":{"stars":8,"repo_name":"edgeone-pages-skills","origin_url":"https://github.com/tencentedgeone/edgeone-pages-skills/blob/HEAD/skills/edgeone-pages-dev/SKILL.md","repo_owner":"tencentedgeone","body_sha256":"0400a4879c2afd361ec654311b819bce2aa5dea4ee3b8c2b4ac90c0d1d72fa98","cluster_key":"76909b94a98aa477ff41edf67c63d9a1656f49c74f435a6c7d77e2689b6c999b","clean_bundle":{"format":"clean-skill-bundle-v1","source":"tencentedgeone/edgeone-pages-skills/skills/edgeone-pages-dev/SKILL.md","attachments":[{"id":"6d76ff5b-bbcb-593e-95e1-4cd70c32754b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6d76ff5b-bbcb-593e-95e1-4cd70c32754b/attachment.md","path":"references/edge-functions.md","size":4034,"sha256":"70531fcecedcf329e2f0a28f86db01cd8b97bbca95a4f553b52af71f037886b6","contentType":"text/markdown; charset=utf-8"},{"id":"6d8bd75b-f9d5-5b48-84e3-8f2c1dcdef71","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6d8bd75b-f9d5-5b48-84e3-8f2c1dcdef71/attachment.md","path":"references/go-functions.md","size":5737,"sha256":"079c43017d062a2c3141614d4873dc761352f15114f4797d17c8246f66004395","contentType":"text/markdown; charset=utf-8"},{"id":"68e5ccde-83cd-56f6-ac6d-35ec108d1bf0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/68e5ccde-83cd-56f6-ac6d-35ec108d1bf0/attachment.md","path":"references/kv-storage.md","size":7792,"sha256":"b20fe3ee5e4ef1815886e87e0517ced8f7f042ccd57faf9a9c8ae264c43b5f7c","contentType":"text/markdown; charset=utf-8"},{"id":"aefa8d33-fce5-5456-8393-74198d5032ea","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/aefa8d33-fce5-5456-8393-74198d5032ea/attachment.md","path":"references/middleware.md","size":4363,"sha256":"23498f8295a6f0ca442c8fad456fdc30c928cdabe6d08a3c8d158d226f548f83","contentType":"text/markdown; charset=utf-8"},{"id":"c6876026-46f2-58c1-ac3f-b2e1bef9d125","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c6876026-46f2-58c1-ac3f-b2e1bef9d125/attachment.md","path":"references/node-functions.md","size":7299,"sha256":"341b2cfdfcc0a006e8428eb53acf4ff96a5079f3b4012268322f281860896d82","contentType":"text/markdown; charset=utf-8"},{"id":"115c307f-5b3f-57bb-958d-5c06f95f0dc0","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/115c307f-5b3f-57bb-958d-5c06f95f0dc0/attachment.md","path":"references/python-functions.md","size":8259,"sha256":"343d4329f6e81b836b80b5f9ec976fc37ffb055552157c6eab3f94c843e00ae7","contentType":"text/markdown; charset=utf-8"},{"id":"cfa5a72a-16eb-5dda-aa07-626018294e75","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/cfa5a72a-16eb-5dda-aa07-626018294e75/attachment.md","path":"references/recipes.md","size":4789,"sha256":"74c7491683dbfb7e9bf420e099a51fb0d33bb2304777a96ab0650b4647da2cbb","contentType":"text/markdown; charset=utf-8"},{"id":"8a0257ae-724b-5db1-8619-aa617969eb7d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8a0257ae-724b-5db1-8619-aa617969eb7d/attachment.md","path":"references/troubleshooting.md","size":3633,"sha256":"69b387ecffa2b6b5c1b39e9cf6bc759f3d3e14218fb2ba0f97d332ed2afbafae","contentType":"text/markdown; charset=utf-8"}],"bundle_sha256":"b68839edfafcc706089a56722d153f611d46192cb223c31d47623c4808c93adc","attachment_count":8,"text_attachments":8,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"skills/edgeone-pages-dev/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"devops-infrastructure","category_label":"DevOps"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"devops-infrastructure","metadata":{"author":"edgeone","version":"4.0.0"},"import_tag":"clean-skills-v1","description":"This skill guides development of full-stack features on EdgeOne Pages — Edge Functions, Cloud Functions (Node.js / Go / Python runtimes), Middleware, KV Storage, and local dev workflows. It should be used when the user wants to create APIs, serverless functions, middleware, WebSocket endpoints, or full-stack features specifically on EdgeOne Pages — e.g. \"create an API\", \"add a serverless function\", \"write middleware\", \"build a full-stack app\", \"add WebSocket support\", \"set up edge functions\", \"use KV storage\", \"create a Go API\", \"build a Python backend\", \"use Flask/FastAPI/Gin on EdgeOne Pages\", \"创建接口\", \"写个API\", \"加个中间件\", \"写后端\", \"搭建全栈应用\". Do NOT trigger for framework-native features (Next.js API routes, Next.js middleware, Nuxt server routes) or generic Express/Koa development outside an EdgeOne Pages project. Do NOT trigger for deployment — use edgeone-pages-deploy instead. Do NOT trigger for other platforms (Cloudflare Workers, Vercel Functions, AWS Lambda)."}},"renderedAt":1782980128201}

EdgeOne Pages Development Guide Develop full-stack applications on EdgeOne Pages — Edge Functions, Cloud Functions (Node.js / Go / Python), and Middleware. When to use this skill - Creating APIs, serverless functions, or backend logic on EdgeOne Pages - Adding middleware for request interception, redirects, auth guards, or A/B testing - Building full-stack apps with static frontend + server-side functions - Using KV Storage for edge-side persistent data - Setting up WebSocket endpoints (Node.js runtime) - Integrating Express, Koa, Gin, Echo, Flask, FastAPI, or Django on EdgeOne Pages - Debugg…