Pages Functions
Serverless API endpoints with file-based routing
Overview
Pages Functions are serverless functions that deploy alongside your static site. They use file-based routing from a functions/ directory at the project root.
File-Based Routing
The file path determines the URL:
functions/api/search.ts → /api/search
functions/api/users/[id].ts → /api/users/:id
functions/pj/my-site/api/search.ts → /pj/my-site/api/search
⚠️ Path Matches Deploy Structure
If your site uses a base path like /pj/my-site/, the functions directory must mirror that path: functions/pj/my-site/api/search.ts serves at /pj/my-site/api/search.
Function Format
Functions export an onRequest handler (or method-specific handlers like onRequestGet, onRequestPost):
interface Env {
KEYWORD_LOGS: KVNamespace;
}
export const onRequestGet: PagesFunction<Env> = async (context) => {
const url = new URL(context.request.url);
const query = url.searchParams.get("q");
// Access KV binding
const logs = context.env.KEYWORD_LOGS;
return new Response(JSON.stringify({ results: [] }), {
headers: { "Content-Type": "application/json" },
});
};
Bindings
Pages Functions access Cloudflare services through bindings defined in wrangler.toml:
compatibility_date = "2024-12-01"
[[kv_namespaces]]
binding = "KEYWORD_LOGS"
id = "abc123def456"
The Env interface in your TypeScript code must match the binding names:
interface Env {
KEYWORD_LOGS: KVNamespace; // matches binding name in wrangler.toml
DB: D1Database; // D1 binding
FILES: R2Bucket; // R2 binding
}
Importing Modules
Functions can import from node_modules. However, the bundler behavior differs from regular Node.js:
// Works -- importing npm packages
import MiniSearch from 'minisearch';
// Works -- importing JSON (with @ts-expect-error for type safety)
// @ts-expect-error JSON import bundled by esbuild
import searchData from './search-data.json';
💡 Tip
For functions that need npm packages, install them before deploying. In CI:
pnpm add -w minisearch # Add the dependency
pnpm dlx wrangler@4 pages deploy deploy --project-name=my-site Local Development
Test functions locally with:
npx wrangler pages dev dist --port 8788
This starts a local server that serves both the static files and the functions.