Functions

The core building block — a handler that receives a Request and returns a Response.

Functions

A Cluster function is a JavaScript or TypeScript module that exports a handler function. It receives a standard Request and returns a Response.

Basic Handler

export function handler(request: Request): Response {
  return new Response("Hello from Cluster!");
}

Async Handler

Handlers can be async — use await for fetch() calls, crypto operations, or any async work:

export async function handler(request: Request): Promise<Response> {
  const data = await fetch("https://api.example.com/data");
  const json = await data.json();
  return Response.json(json);
}

Routing

Route matching is done in your handler code using the URL and Request APIs:

export async function handler(request: Request): Promise<Response> {
  const url = new URL(request.url);

  if (url.pathname === "/api/hello" && request.method === "GET") {
    return Response.json({ message: "Hello!" });
  }

  if (url.pathname === "/api/time") {
    return Response.json({ time: new Date().toISOString() });
  }

  return Response.json({ error: "Not found" }, { status: 404 });
}

You can also use URLPattern for more complex routing:

const pattern = new URLPattern({ pathname: "/users/:id" });

export function handler(request: Request): Response {
  const match = pattern.exec(request.url);
  if (match) {
    const userId = match.pathname.groups.id;
    return Response.json({ userId });
  }
  return new Response("Not found", { status: 404 });
}

Environment Variables

Access environment variables via process.env:

export function handler(request: Request): Response {
  const apiKey = process.env.API_KEY;
  return new Response(`Key starts with: ${apiKey?.slice(0, 4)}...`);
}

See Environment Variables for how to set them.

Organizations

Functions belong to organizations. When you first deploy or run ccp init, you select which organization to deploy to. A single organization can have many functions.

Managing Functions

# Context-aware listing:
#   inside a linked project  -> that function's deployments
#   outside one              -> every function in the organization
ccp list        # or: ccp ls
ccp ls --org-id <org>   # outside a project: choose the org explicitly

# Delete the linked function
ccp remove      # or: ccp rm

# Link current directory to an existing function
ccp link

ccp ls adapts to where you run it, the same way ccp compute ls does:

  • Inside a linked project (a .cluster/config.json with a function_id) it lists that function's deployments, headed Deployments for <org>/<function>.
  • Outside a project it lists every serverless function in the organization — name, canonical URL (shown only once a function has a live production deployment), custom domains, cron, and last update — headed Functions in <org>. The organization is resolved from --org-id, then the project config, then an interactive picker (auto-selected when you belong to a single org; in headless/non-interactive mode with multiple orgs and no --org-id, it errors rather than prompting).

What's Not Available

Cluster runs V8 isolates, not Node.js. There are no Node.js built-in modules:

  • No fs, path, os, child_process, net, http
  • No Buffer (use Uint8Array and TextEncoder)
  • No require() (use ES modules — the bundler handles modules for you)

Use fetch() for HTTP requests to external services. See the full Runtime API reference.

On this page