Git and direct deployments
Choose Git integration or Direct Upload
Pick the deployment source before creating the project because switching models later may require a new project.
A Pages project gets its files in one of two ways, and you choose which one when you create the project.
With Git integration, you connect a GitHub or GitLab repository. Every push triggers a build on Cloudflare’s servers, and the build output becomes a deployment. Cloudflare owns the build.
With Direct Upload, you build somewhere else and hand Cloudflare the finished directory. That somewhere can be your laptop, your own CI, or the dashboard’s drag-and-drop uploader. You own the build.
Why the choice matters up front
The Pages docs warn that a Git-integrated project and a Direct Upload project cannot switch to the other model later. If you start with Direct Upload and later want pushes to deploy automatically, you create a new project and move the custom domain over.
So decide before creating anything. The question is: who should build the site, and who decides when a release happens?
Git integration fits when the repository is the release process. Merge to master, the site updates. Preview deployments for pull requests come for free.
Direct Upload fits when you already have CI that runs tests, builds, and gates releases. Cloudflare only receives the result. It also fits a site you build by hand and publish once in a while.
Deploy a directory yourself
Build first, then inspect the directory you plan to upload:
npm run build
find dist -maxdepth 2 -type f | sort | head
npx wrangler pages deploy dist --project-name practice-site
Replace dist with the real output directory. Open the deployment URL and one static asset before attaching a domain. If CI owns the upload, run the same build there and keep the exact commit with the deployment.
The find step is the one people skip. It shows you what you’re about to publish. If you see package.json and src/ in that list, you pointed at the wrong directory, and every page will 404 after the deploy.
A successful upload ends like this:
✨ Deployment complete! Take a peek over at
https://a1b2c3d4.practice-site.pages.dev
If the project doesn’t exist yet, Wrangler offers to create it. That new project is a Direct Upload project, and it stays one.
One build, one commit
Whichever model you pick, keep the build and the source commit together. With Git integration, Cloudflare records the commit for you. With Direct Upload, pass it yourself:
npx wrangler pages deploy dist --project-name practice-site --commit-hash $(git rev-parse HEAD)
When something breaks, “which commit is live?” must have an instant answer.
Try this: write one sentence stating whether Cloudflare or your CI should build the site, then create the matching project type and deploy once.
Lesson completed