Skip to content

Build settings

A build reads the commit and works out what to run. Anything you set on the Worker’s Settings tab, under Build and git, wins over what it finds. Every deployment’s log starts with the plan it chose, such as Plan: framework=astro pm=pnpm root=. install=… build=pnpm run build output=dist.

Setting Left empty Notes
Branch main Pushes to any other branch aren’t built.
Build on push On Off, only Deploy now builds.
Root directory The repository’s root Where package.json, the lockfile and wrangler.jsonc are looked for, and where commands run. For a monorepo, the app’s folder.
Install command From the lockfile See below.
Build command From the framework See below.
Output directory From wrangler.jsonc or the framework Setting it makes the build deploy that folder of static files, even when there’s a wrangler.jsonc.
Node version 22 Shown in the log; the build runs on the Node.js that comes with the build sandbox.

New Workers start with the defaults in Sites › Settings. From the API, PATCH /api/v1/sites/{site} changes branch, buildOnPush, rootDir, installCommand, buildCommand, outputDir and nodeVersion; an empty string goes back to what the build finds.

The lockfile in the root directory picks the package manager, and the install runs frozen to it:

Lockfile Install command
pnpm-lock.yaml pnpm install --frozen-lockfile (pnpm 10 is installed first if the sandbox has none)
bun.lock or bun.lockb bun install --frozen-lockfile (Bun 1)
yarn.lock yarn install --frozen-lockfile (Yarn 1)
package-lock.json npm ci

Without a lockfile, the packageManager field of package.json picks it (npm otherwise), and the install isn’t frozen. Without a package.json there’s no install at all. The installed dependencies are cached between builds while package.json and the lockfile stay the same.

The framework comes from package.json’s dependencies, in this order:

Found Build command What’s deployed
@opennextjs/cloudflare npx opennextjs-cloudflare build The Worker OpenNext writes.
A wrangler.json, wrangler.jsonc or wrangler.toml, @cloudflare/vite-plugin or @tanstack/react-start The build script, else npx astro build, npx nuxt build or npx vite build when that’s a dependency The Worker and assets the wrangler config names.
astro The build script, else npx astro build dist
next npx --yes vinext build dist/client, with dist/server/index.js as the Worker
@sveltejs/kit The build script, else npx vite build build
nuxt The generate script if there’s a build script, else npx nuxt generate .output/public
@11ty/eleventy The build script, else npx @11ty/eleventy _site
vite The build script, else npx vite build dist, as a single-page app
A build script The build script, run with the package manager The first of the output folders below
Nothing None The first of the output folders below, or the root itself without a package.json

Scripts run as <package manager> run build. With a wrangler.jsonc and a Vite plugin that writes .wrangler/deploy/config.json (the Cloudflare Vite plugin does), the build deploys the config that file points at.

When nothing names the output, the build takes the first of dist, build, out, public, .output/public and _site that exists. A _worker.js file in it is deployed as the Worker.

The install and build run with NODE_ENV=production. Of the site’s variables, only those a framework inlines into the browser’s code reach the build: names starting with PUBLIC_, VITE_, NEXT_PUBLIC_, ASTRO_ or NUXT_PUBLIC_. The rest, and every secret, reach only the deployed Worker.

The Runtime section of the Worker’s Settings tab, which applies from the next deploy:

  • Compatibility date and compatibility flags. A compatibility_date in the site’s own wrangler.jsonc wins over the setting, and its compatibility_flags are added to the setting’s. nodejs_compat is always on. global_fetch_strictly_public is always taken out, since Outbound already decides what a site may reach.
  • Placement. Default, or Smart Placement, which runs the Worker closer to the services it calls.

New Workers start with Sites › Settings’ compatibility date (2026-10-01 unless changed) and flags (nodejs_compat).