Cloudflare deployment field note
Fixing Deploy to Cloudflare in a monorepo: expose the root contract
A deploy badge can look correct while every new user reaches “No Wrangler configuration detected.” In a workspace repository, the fix is to make the target root a complete deployment contract.
The failure appears after the badge works
Babili already had a working production deployment and a valid Deploy to Cloudflare link. Its Wrangler configuration lived under workers/api, where local and production commands could find it. A new visitor followed the badge, however, and Cloudflare reported No Wrangler configuration detected before falling back to automatic project configuration.
That is the dangerous version of a deployment bug: maintainers can keep shipping while the public self-host path is broken. The badge tests only navigation. It does not prove that the target directory exposes everything the setup flow needs.
The target directory is the contract boundary
Cloudflare analyzes the directory named by the deploy URL. If the URL targets the repository root, nested workspace configuration is not a substitute for a root deploy contract. The root needs a Wrangler configuration plus build and deploy scripts that work from that directory.
{
"scripts": {
"build": "npm run build --workspace @example/web && npm run build --workspace @example/api",
"deploy": "npm run build && wrangler deploy -c wrangler.jsonc"
}
}
The root scripts can delegate to workspaces. What matters is that a stranger—and Cloudflare's project analysis—can start at the target root without knowing the repository's internal layout.
Keep the public template smaller than production when necessary
Babili's production Worker uses an optional Analytics Engine binding for its own aggregate growth measurement. Cloudflare does not list Analytics Engine among the resources its deploy button automatically provisions, so the public root template omits that binding. Independent instances work without sending Babili measurement events.
Do not copy every production binding into a one-click template by reflex. Include only resources the platform can provision or the deployer can supply during setup. Otherwise the button turns an optional integration into a first-run failure.
Two configurations require a drift test
A root template and a workspace production configuration can quietly diverge. Babili runs a repository check that compares the Worker entry point, Durable Object binding, migration tag, assets directory, compatibility date, and resolved paths. The build fails if the shared runtime contract drifts.
This keeps intentional differences explicit: production can retain an optional binding, while the independently deployable root template stays minimal and reproducible.
Test the public journey, not the maintainer journey
- Open the public repository as a visitor would.
- Follow the published deploy button rather than a private dashboard shortcut.
- Select an account and wait for repository analysis.
- Confirm the detected build command, deploy command, and root path.
- Stop and investigate if the fallback warning appears.
- Run both root and workspace Wrangler dry runs in continuous integration.
Cloudflare documents the supported button format, scripts, and provisioned resources in its Deploy to Cloudflare guide. The Babili repair is public in pull request 89, including its root configuration and parity check.
The reusable lesson
A one-click deploy feature is an external API. Its callers do not share the maintainer's working directory, cached settings, or mental model. Treat the target root as a stable interface, make every dependency visible there, and test it from the outside.